Walk into any hair salon and the consultation starts with a question: what are you thinking? The client describes something approximate — a bit lighter, more red, like that actress. The stylist nods. The client hopes they mean the same thing. They often do not.
Virtual hair color try-on solves this in 1.2 seconds. The client uploads a photo, selects a color, and sees themselves. Not an approximation. Not a stock model. Themselves, with the exact color the stylist will apply. The consultation goes from vague to precise. Bookings convert. Surprise reactions drop. Rebooking rates increase.
Salon booking platforms — Booksy, Vagaro, Fresha, Mindbody — collectively serve hundreds of thousands of stylists and tens of millions of appointment slots per year. None of them currently offer virtual hair color consultation as a native feature. The feature does not exist in any of their SDKs. The gap is not technical. It is structural: no one has built the API layer that makes this trivial to embed.

| Stack | Infra /mo | AI team | Total cost | Revenue | Margin |
|---|---|---|---|---|---|
Runflow 10% volume discount applied | $1.1K | $0 | $1.1K | $8.0K | 87% |
Cloud API + manual QA similar pricing · no auto-QA · part-time engineer needed | $1.2K | ~$5K | $6.2K | $8.0K | 23% |
Self-hosted GPU raw compute · full-time AI engineer required | $400 | $12K | $12K | $8.0K | loss |
Runflow Sentinel — built-in quality control layer that automatically detects and discards failed or low-quality outputs before delivery. You only pay for images that pass QA. No engineer needed to babysit the pipeline.
Pricing based on Runflow published rates (June 2026) with automatic volume discounts. Revenue column is illustrative — actual client pricing varies by vertical and contract size. GPU self-hosted estimate uses $0.04/img raw compute cost.
Why this feature does not exist in salon platforms yet
Consumer-facing hair color changers have existed for years. YouCam Makeup, Garnier Virtual Try-On, L'Oreal's Color Genius — all of them let individuals try colors before visiting a salon. They are consumer apps. They are not APIs. They are not embeddable. They do not generate a consultation asset that a stylist can open on their iPad before starting work.
The B2B API layer — a single endpoint that accepts a photo plus a color specification and returns a processed image — does not have a dominant player. The reason is timing. Foundation models capable of realistic hair segmentation with color transfer that preserves texture, shine, and shadow became viable at scale in 2024–2025. The salon platform companies were not watching the model layer. They were building calendars and payment flows.
That creates an opening. The platform that ships this feature first gets a positioning advantage that compounds. Stylists recommend platforms that make their consultations better. Clients rebook at salons where the experience felt premium. Premium starts at the try-on step.
How the pipeline works
The hair color simulation pipeline runs five stages. Each stage is a ComfyUI node. The full workflow can be exported as a JSON definition and deployed as a single API endpoint.
Stage 1 — Face and hair detection
The input image is processed through a face detection model to locate the head region and establish bounding coordinates. This step filters non-portrait inputs before they reach expensive processing stages. A valid portrait — frontal or 3/4 angle, hair visible, face detected — proceeds. Other inputs return a structured error.
Stage 2 — Hair segmentation
A segmentation model isolates the hair region with pixel-level precision. The mask separates hair from skin, background, clothing, and accessories. Hair at the edges — flyaways, curls escaping from the main volume, baby hairs at the hairline — is included in the mask. This step determines output quality more than any other. A coarse mask produces a result that looks painted. A precise mask produces a result that looks like a different dye job.
The segmentation model used here is a fine-tuned version of SAM (Segment Anything Model), additionally trained on a dataset of 200,000+ hair portraits covering straight, wavy, curly, and coily textures across a full range of natural and fashion colors. Hair type coverage matters because curly and coily textures have significantly more edge complexity than straight hair and are routinely underserved by generic segmentation models.
Stage 3 — Color transfer
Color transfer rewrites the masked region using the target color while preserving the underlying luminance structure — the highlights, shadows, and reflections that give hair its three-dimensional appearance. This is the step where most consumer tools fail. They apply a flat color overlay. The result looks like the hair was painted in a photo editor, not dyed in a salon.
The pipeline uses a diffusion-based inpainting approach conditioned on the luminance map. The target color is specified as an HSL value, not a hex code, because hue-saturation-lightness maps directly to how hair color actually works: base tone, saturation (vibrancy vs. muted), and lightness (level lift). A Wella Professional color specified as 7/3 (medium blonde, golden) maps to a precise HSL range. The platform can expose this directly or abstract it behind a color picker.
Stage 4 — Texture preservation
After color transfer, a texture refinement pass restores fine detail that the inpainting step can smooth over — individual strands, natural variation in tone across the hair mass, the micro-shadows between curls or layers. This stage is what separates a result that looks real at full zoom from one that looks real only at thumbnail size.
Stage 5 — Output compositing
The processed hair region is composited back onto the original image with feathered edge blending. The output is a full-resolution image identical to the input except for the hair color. No background change. No skin tone change. No lighting change. The client sees a realistic preview of what the color will look like on their face, with their features, in their photo.
What the API call looks like
import requests
response = requests.post(
"https://api.runflow.io/v1/run",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"workflow": "hair-color-tryon-v2",
"inputs": {
"image_url": "https://your-cdn.com/client-photo.jpg",
"target_color": {
"hue": 28,
"saturation": 65,
"lightness": 45,
"label": "copper-auburn"
},
"preserve_highlights": True,
"output_format": "webp"
}
}
)
result = response.json()
# result["outputs"]["image_url"] → processed image CDN URL
# result["outputs"]["processing_ms"] → 1140
# result["outputs"]["confidence"] → 0.94 (hair segmentation confidence)The endpoint is synchronous for images under 4 megapixels and returns a CDN URL within 1.5 seconds. For batch processing — the use case where a platform pre-generates a set of color previews for a client profile — an async variant accepts up to 20 images per request with a webhook callback.
The buyer is not the salon — it is the platform
This distinction matters for how you build and price the integration. Individual stylists do not buy APIs. Salon owners do not have engineering teams. The buyer is the platform that 50,000 salons are already using.
Booksy has over 15 million monthly active users. Vagaro processes over 30 million appointments per year. Fresha has over 100,000 venues on its platform. Each of these platforms has a developer ecosystem, a product roadmap, and a partnership model. They are not building this feature themselves. They will white-label or integrate an API that delivers it.
The integration pattern for a salon booking platform looks like this: the virtual try-on becomes a widget inside the booking flow. After the client selects a color service — balayage, full color, highlights — the platform surfaces the try-on step. The client uploads a selfie or uses their profile photo. They preview three to five color options. They select one and attach it to their booking. The stylist receives the booking with the reference image. The consultation starts with shared context instead of verbal approximation.
Hair dye brands: the other B2B buyer
Professional hair dye brands — Wella Professional, Schwarzkopf Professional, L'Oreal Professionnel, Redken — sell through salons and through direct-to-consumer retail. They all have digital presence. None of them have a native hair color changer embedded in their product discovery pages that returns realistic results at photo-realistic quality.
The use case for a brand like Wella Professional is product-specific. A client browsing the Illumina Color range wants to see shade 7/43 (medium blonde, copper-red) on their actual hair, not on the generic model on the product page. A conversion-rate-optimized hair color changer tied directly to the product catalog — one API call per shade, triggered from a hover or click on any swatch — converts browsers into buyers.
The brand buyer is the digital marketing team. They measure success in conversion rate and average order value. The integration is a JavaScript widget deployed on product pages. The API is called client-side with a public key scoped to read-only workflow access. The client photo stays in the browser until the user explicitly submits it.
Build vs. buy: the real cost comparison
Platform engineering teams evaluating this feature face a standard make-or-buy decision. The numbers favor API-first unless the platform has existing ML infrastructure and a dedicated vision team.
| Cost component | Build in-house | API (Runflow) |
|---|---|---|
| GPU infrastructure (A100 cluster, 3 reserved) | $18,000/mo | $0 |
| ML engineer (segmentation + color transfer) | $12,000/mo | $0 |
| Model maintenance and retraining | $3,000/mo | $0 |
| Inference cost at 500K images/mo | included above | $1,500–3,000/mo |
| Cold start / availability SLA engineering | $4,000/mo | $0 |
| Total monthly cost | ~$37,000/mo | $1,500–3,000/mo |
| Time to first working demo | 3–5 months | 2 days |
The $37,000/month build cost assumes the team reaches production quality in 3–5 months. Most teams underestimate the segmentation work. Straight hair on a white background is solved. Curly hair against a busy background, flyaways at the hairline, gray roots blending into dark hair — these edge cases take months of training data and evaluation to handle reliably at the quality level clients expect. The API has already solved them.
Color specification: mapping salon color systems to API inputs
One integration challenge that does not come up in consumer apps but matters significantly in the B2B context is color system mapping. Salon color is specified in professional numbering systems — the Wella System, the ICC numbering system, the Schwarzkopf ChromaID system. A booking platform that wants to show clients a preview of the specific formula their stylist has chosen needs to map between the professional color code and the API's color space.
The mapping is not trivial but it is solvable. A lookup table of the major professional color systems, mapping each shade to an HSL range with variance bounds, covers 95% of in-salon colors. The remaining 5% — custom formulations, multi-process results like double-process blondes — require a color picker fallback where the stylist selects from a rendered range rather than entering a code.
# Example: Wella Illumina Color shade mapping
COLOR_MAP = {
"7/43": {"h": 28, "s": 68, "l": 52, "label": "Medium Blonde Copper-Red"},
"6/16": {"h": 195, "s": 25, "l": 38, "label": "Dark Blonde Ash-Violet"},
"9/60": {"h": 42, "s": 72, "l": 72, "label": "Very Light Blonde Natural-Red"},
"5/81": {"h": 220, "s": 18, "l": 30, "label": "Light Brown Ash-Pearl"},
# ... full table: 200+ shades across Illumina, Koleston Perfect, Color Touch
}
def color_for_shade(shade_code: str) -> dict:
if shade_code in COLOR_MAP:
return COLOR_MAP[shade_code]
raise ValueError(f"Unknown shade: {shade_code}. Use color picker fallback.")Privacy and photo handling
Any feature that asks clients to upload photos of themselves requires clear data handling. The implementation pattern that works for salon platforms: the photo is processed in memory, never stored on the API provider's infrastructure beyond the request lifecycle, and the output image URL expires after 24 hours. The platform's privacy policy covers the rest.
For platforms in the EU — which covers most of Fresha's and Treatwell's user base — the photo is personal data under GDPR. The API processes it under data processing agreement terms. The platform is the data controller. The API provider is the processor. This structure is standard and does not require custom legal work beyond a standard DPA.
Hair types covered
The segmentation model was validated across four major hair texture categories. Coverage matters because mainstream try-on apps have historically performed well on straight hair and poorly on curly and coily textures — which represent a significant share of salon clients who have historically been underserved by digital beauty tools.
| Hair type | Segmentation accuracy | Color transfer quality | Notes |
|---|---|---|---|
| Type 1 (straight) | 97.2% | Excellent | Baseline; most training data |
| Type 2 (wavy) | 95.8% | Excellent | Minor edge artifacts at hairline |
| Type 3 (curly) | 93.1% | Very good | Additional refinement pass on curl edges |
| Type 4 (coily/afro) | 91.4% | Good | Works best with defined texture; diffuse edges reduce confidence |
Type 4 hair at 91.4% segmentation accuracy is significantly better than comparable consumer tools — most of which do not publish accuracy metrics by hair type, which in practice means curly and coily results are treated as an acceptable casualty. For a platform targeting a diverse client base, this coverage difference is not cosmetic. It is a product decision with commercial consequences.
Latency benchmarks
Perceived responsiveness is the most important UX metric for a try-on feature. A user who clicks a color and waits more than two seconds will click again, assume it is broken, and abandon. The pipeline is optimized for the sub-1.5 second target.
| Input resolution | Segmentation (ms) | Color transfer (ms) | Compositing (ms) | Total (ms) |
|---|---|---|---|---|
| 480×640 (mobile selfie) | 180 | 420 | 85 | 685 |
| 1080×1350 (phone portrait) | 240 | 680 | 120 | 1,040 |
| 2048×2560 (high-res) | 310 | 890 | 145 | 1,345 |
| 4000×5000 (DSLR) | 480 | 1,340 | 190 | 2,010 |
For in-app use in a booking flow, mobile selfie resolution (480×640) covers 80% of sessions. Platforms can downsample on the client side before upload without visible quality loss at the preview size the try-on widget renders at. This keeps the median response time under 700ms for most users — well within the perceived-instant threshold.
Integration options
Option 1: REST API (backend integration)
The platform's backend calls the API with the client's photo and desired color. The API returns a CDN URL. The platform serves the result to the client. This pattern keeps the API key on the server, adds one network hop, and gives the platform full control over caching and rate limiting.
Option 2: JavaScript SDK (frontend integration)
A scoped public key allows direct API calls from the browser. The photo is never sent to the platform's backend — it goes directly from the client device to the inference endpoint and back. This reduces latency by eliminating the backend hop and simplifies the platform's data handling footprint. The public key is scoped to the specific workflow and cannot be used for other operations.
Option 3: Embedded widget
A pre-built React component handles the full UX: photo upload or camera capture, color selector, before/after display, and result sharing. Platform teams integrate it with a single import and a configuration object. No custom UI work required. Styling is configurable via CSS variables to match the platform's design system.
import { HairColorWidget } from "@runflow/hair-tryon-sdk"
// Drop into any booking flow step
<HairColorWidget
apiKey={process.env.NEXT_PUBLIC_RUNFLOW_KEY}
colors={stylist.colorPalette} // your color catalog
onSelect={(result) => {
setBookingNote(result.selectedColor)
setPreviewUrl(result.imageUrl)
}}
theme={{ primary: "#1a1a1a", radius: "8px" }}
/>Pricing model for platform resellers
Platform economics for a try-on feature embedded in a booking flow look like this: the platform pays per image processed, passes the cost to salons as a subscription feature tier, and captures margin on the difference. A salon that books 200 color appointments per month generates roughly 200 try-on images if the feature is surfaced at the right step. At $0.005 per image, that is $1.00 per salon per month in API cost. A feature tier priced at $15–20 per month runs at 93–95% gross margin on the try-on cost alone.
| Tier | Price per image | Min monthly | SLA | Best for |
|---|---|---|---|---|
| Pay-as-you-go | $0.006 | None | 99.5% | Testing and small volumes |
| Growth | $0.005 | $50/mo | 99.9% | Platforms up to 50K images/mo |
| Scale | $0.003 | $500/mo | 99.95% | Platforms above 50K images/mo |
| Enterprise | Custom | Custom | 99.99% + SLA | White-label + dedicated infra |
What a virtual hair color try-on feature ships in
A working integration has five components. Most platform teams with a mid-level frontend engineer and access to the API can ship a beta in two working days.
Photo capture or upload. A camera button for mobile users, a file input for desktop. No special handling required — the API accepts JPEG, PNG, and WebP, and returns a consistent error for non-portrait inputs rather than a degraded result.
Color selector. A swatch grid of the salon's color offerings, or a free-color picker for platforms without a structured catalog. The selector passes an HSL value or a catalog reference to the API call.
Before/after display. A simple side-by-side or slider comparison showing the original and the try-on result. The output image is served from a CDN URL with a 24-hour expiry — sufficient for the booking session.
Booking attachment. The selected color and the output image URL are attached to the appointment record. The stylist receives them in the booking notification and can open the reference image before the client sits down.
Analytics event. A single event fired when the client confirms a color selection. Platform product teams can measure try-on adoption rate, most popular colors by salon, and correlation between try-on use and rebooking rate.
The competitive window
Consumer hair color apps already have large audiences. Free hairstyle try-on tools, virtual hair color changers, AI hairstyle apps — these exist and they attract consumer traffic. But consumer apps are not the competition for a B2B API. The competition is the absence of any API, which means platforms currently have to build from scratch or go without.
The market is moving. L'Oreal has invested in augmented reality tools for in-salon use. Wella has exploration programs in digital consultation. Neither is shipping an embeddable API that a third-party platform can integrate. The window where an API player can establish the standard before the brands ship their own is measured in months, not years.
For a platform engineering team evaluating this feature today, the build-vs-buy math is not close. The API delivers production-quality results in two days. The in-house build delivers comparable quality in five months — if the segmentation work goes well. The platform team's time is better spent on the booking flow, the stylist experience, and the pricing model than on training hair segmentation models.
The consultation problem has always been structural. The client and the stylist enter the conversation with different reference points. Virtual try-on does not replace the stylist's expertise. It gives both parties the same starting image. That is a much easier problem for AI to solve than replacing the consultation itself — and it is the problem the market will pay to have solved first.