Between CyclesOpen the app

How it works, and where it stops

Between Cycles is a measuring tool, not a diagnostic one. This page lists exactly what it measures, how it decides something has changed, what is backed by evidence and what is not.

Why skin, why now

Skin reactions occur in roughly 90% of people treated with EGFR inhibitors, typically starting in weeks 1–3 and peaking at weeks 3–4, mostly on the face, scalp and upper body. Other chemotherapy drugs cause dryness and darker patches. Patients are asked to report changes, but are rarely given a way to measure them.

U.S. Pharmacist · ESMO OncologyPRO · MASCC Skin Toxicity Study Group

Reporting symptoms early matters. In a randomised trial of 766 people on chemotherapy, online symptom self-reporting with alerts to nurses was associated with longer median survival (31.2 vs 26.0 months). That trial covered general symptoms, not skin photos, but it is the case for structured self-monitoring.

JAMA / Memorial Sloan Kettering

What is measured

Each scan is a front-facing photo analysed by the YouCam AI Skin Analysis API. We request 8 concerns and focus on four that match documented treatment side effects:

  • Redness: Inflammation that often comes with treatment-related rash.
  • Bumps & spots: Targeted therapies (EGFR inhibitors) commonly cause an acne-like papulopustular rash on the face.
  • Dryness: Dry skin (xerosis) is a frequent side effect of many cancer treatments.
  • Dark patches: Some chemotherapy drugs cause hyperpigmentation.

We use the API's raw_score, not its ui_score. The vendor documents the UI score as adjusted upward to be encouraging, which is right for a beauty app and wrong for tracking change. We show level = 100 − raw score, so a rising line means a concern is more visible.

Perfect Corp. YouCam API

How a change is decided

Photo-based scores move a little between shots even when skin hasn't changed: light, angle and distance all play a part. So the app starts with 3 baseline scans taken minutes apart. Their spread is your personal measurement noise.

SEM = within-person SD of the baseline scans
MDC95 = 1.96 × √2 × SEM (minimum 3 points)
change counts only if |latest − baseline mean| > MDC95

This is the minimal detectable change used in test–retest reliability studies: a difference larger than MDC95 is unlikely (under 5%) to be noise alone. A concern with noisier scores automatically gets a wider band, so it needs a bigger change to be flagged. The floor of 3 points stops three near-identical baseline photos from making the band unrealistically narrow.

Repeatability: what we measured

SessionPhotosRedness SD / MDCBumps & spots SD / MDCDryness SD / MDCDark patches SD / MDC
Same light
Same spot and room light, phone at arm's length, 5 photos taken one after another (1 rejected by the API for head angle).
40 on every photo*1.2 / 3.31.2 / 3.30.5 / 1.4
Different light
Three different lights, same session: near a window, under a ceiling light, and facing away from a bright light.
30 on every photo*2.9 / 85.1 / 14.12.2 / 6.1

SD = how much the score moved between photos of the same unchanged face; MDC = the 95% minimal detectable change that follows from it (1.96 × √2 × SD). One person, photos taken minutes apart, each cropped identically to the face because they were taken from further away than the in-app camera guide allows. A small sample: it shows the size of the effect, not a population figure.

In matched light the noise band is about 3.3 points, close to the 3-point floor the app never goes below, so that floor is grounded in a measurement rather than a guess.

Change the light and the band widens: dryness from 3.3 to 14.1 points, bumps from 3.3 to 8. That is why every scan asks for the same spot and light, and shows your first baseline photo faintly over the camera so each scan is framed the same way.

* Redness read 0 on every photo of this face, so this run says nothing about redness noise; the app falls back to the 3-point minimum. A score stuck at zero is itself a reason for the skin-tone caution below: a flat redness score doesn't prove there is no redness.

When the app says to call

Some things a photo can't see. Each check-in asks about them, and any of these switches the app to “Contact your care team today”, whatever the scores say:

  • Fever or chills
  • Blisters, peeling or open skin
  • Yellow crusts, pus or skin that feels hot
  • Rash that is painful or stops me doing daily things
  • Rash spreading quickly to large areas
  • Sore, red or swollen eyes

A rise in a watched concern beyond the normal range, or milder symptoms, become “Worth mentioning to your care team”.

Skin tone and redness

Redness is harder to see on deeper skin, for clinicians and for cameras, and treatment rash on darker skin is under-documented. So on the first baseline photo the app runs the YouCam AI Fitzpatrick Skin Type API once (types I–VI). For types V and VI, every result carries a plain note that a steady redness score doesn't rule out a rash, and that symptom answers count as much as the photo. The thresholds themselves are not changed: we have no data to justify a different number, so we say so instead of inventing one.

Skin type is used only for this note. It is stored on the device, never used to rank or compare people, and the app works without it.

Current Oncology · Perfect Corp. YouCam API

Hair density

Hair checks use the YouCam AI Hair Density Detection API, which returns one of four documented density levels and a continuous score from a photo taken with the head lowered. The score's range isn't documented (in our tests a “medium” photo scored 1.71 and a “low” one 0.92), so the level is the headline and the score only draws the trend. The first two checks set a starting point; later checks are compared with it. We haven't measured this score's photo-to-photo noise yet, so moves under 0.5 are shown as steady. This is most useful for people using scalp cooling, which preserved hair in about half of patients in a randomised trial.

Nangia et al., JAMA · Perfect Corp. YouCam API

Product checks

The ingredient checker is a fixed list of 10 rules, not an AI model, so the same label always gets the same answer. When a label is photographed, a vision model only transcribes the list; the person checks the transcription, and the rules decide. Fatty alcohols (cetyl, cetearyl), benzyl alcohol and sunscreen salicylates are deliberately excluded from the alcohol and acid rules.

The same rules run over a snapshot of real products from Open Beauty Facts, an open database (ODbL), to make the treatment-friendly picks and the shelf audit. Before publishing the numbers we listed every ingredient each rule matched across the catalogue and removed two false positives this found (phenoxyethanol read as an alcohol, urea preservatives read as moisturisers). Both are now unit tests.

Picked for your skin today. After a check-in, each change maps to what the guidance above says helps: more bumps or redness to a gentle soap-free cleanser, more dryness (or reported dryness or itch) to a moisturiser with hydrating ingredients, darker patches to a daily sunscreen. Each slot is filled with catalogue products that pass every rule and contain that kind of ingredient, ranked by how many they contain. Nothing is suggested when the advice is to call the care team. There are no sponsored placements.

The shop badge. The same rules are served as a public endpoint (/api/check) and a two-line embed (/badge.js) that shows “Gentle during treatment”, “Ask your care team first” or “Not advised during treatment” on a product page, with the reasons and sources one tap away. Only the public ingredient text is sent.

Measured: label reading and the catalogue

Label photos. We sent 12 real photos filed as ingredient panels on Open Beauty Facts through the app's own label route (2026-11-01) and compared the result with the human transcription on Open Beauty Facts, using the same parser and rules as the app.

11/11

same verdict and flags as the human transcription

92%

of listed ingredients recovered (avg)

93%

of read ingredients that were on the label (avg)

2.6 s

median time, slowest 4.1 s

1 of 12 photos returned no list: in our run that photo showed marketing text, not the ingredient panel, so declining was correct. Twelve labels is a small sample; the script to repeat it is scripts/label-bench.mjs.

Catalogue. Across 1,033 real products in eight categories, 212 (21%) have nothing on the watch-list. Fragrance is the most common reason in every category.

Measured vs curated

  • Measured by API: skin concern scores and masks, skin type, hair density, hairstyle previews.
  • Computed by us, in code: baselines, MDC95 bands, change flags, product verdicts, catalogue pass rates, product suggestions, shop badges.
  • Curated by us: the ingredient rules and symptom list, each tied to the sources below.
  • Read by AI: ingredient lists transcribed from label photos, always shown for the person to check.
  • Synthetic: the demo journey (labelled “Demo data”) and the example ingredient lists.

Limits, plainly

  • The scores come from a cosmetic skin model. They have not been validated against clinical grading (CTCAE or the MASCC EGFR inhibitor skin toxicity tool).
  • Only the face is analysed. Rash on the scalp, chest or back, and hand-foot reactions, are out of scope.
  • Consistency of lighting and position matters; the baseline captures it, but a very different setup can still produce false changes.
  • The app never suggests prescription treatments. Questions for the care team are generated instead.
  • A proper validation would compare app levels with clinician grades across skin tones in a prospective study.

Sources