A zinc sunscreen's label tells you how much zinc oxide is in it. It doesn't tell you how white it's going to look on your face, and you usually find that out after you've already bought the bottle.
That gap hits some people a lot harder than others. In a 2024 dermatology survey, 25% of respondents with skin of color said white cast was a concern, compared to 7% of non-Hispanic White respondents, and 41% said they didn't know how to find suitable products (Wang et al., J Drugs Dermatol 2024).
So I built Cast Forecast for the YouCam API Skin AI & eCommerce VTO Hackathon. You take a selfie, pick a mineral sunscreen, and it shows that bottle's predicted white cast on your own face before you buy it.
No selfie handy? Tap Use a sample face and you'll see recorded results without up anything.
Every prediction starts from the bottle's FDA label, the zinc oxide percent, linked to its DailyMed page. My model is fitted to the raw data of a 2025 PLOS ONE study of 13 volunteers (Maldonado Lopez et al.). Tested on data it never saw, it misses by 1.61 L* on average, and 1.80 on darker skin. Every result shows its range.
It also refuses instead of guessing. If your skin is deeper than the study covered, or the zinc is outside 5 to 30%, you get no number and a sentence saying why.
One thing it shows really clearly is that the same bottle is predicted to leave more cast on deeper skin, from +5.3 to +8.3 L* across five tones.
You can check the main number yourself:
curl -s https://cast-forecast.vercel.app/api/label-model
That returns the 1.61, computed by the shipped code from the study's raw data.
My first plan was to measure every bottle myself, on cards and on skin, and run it through a film model. I decided to ship without in-person testing, so I needed a prediction I could actually defend.
I tested a simple model based on the label's zinc percent against my film model, on data neither one had seen, and the simple one won by a lot (1.61 versus 4.79 L*). So I went with the simple one and I show its error on every number.
The makeup try-on failed my first test when I used coverage as the strength. When I switched to color intensity, it passed every check, and the lightening followed a smooth curve. I ran 16 renders of my own selfie across the full strength range and fitted that curve (R² 0.98). Now the app turns it around to pick the strength for each bottle and tone.
The skin tone analysis gave the same answer every time for the same photo, but it barely moved when I made the photo brighter. It reports a tone corrected for lighting, not the color in the photo. That's good for a shopper, but it meant I couldn't use it as a measurement, so the Fitzpatrick analysis suggests a tone and the shopper confirms it.
Every cast is a prediction from the label, not a measurement on a person, and the render was calibrated on one person (me). It shows how a sunscreen looks, not how well it works.
If you've ever bought a mineral sunscreen and regretted it the first time you put it on, I'd really love to know which one it was.