Protanopia color simulator
The protanopia color simulator shows how one opaque sRGB color is transformed for a viewer without functional long-wavelength cone response, often described as red blindness.
Run — free
Enter a hex value or integer RGB channels and receive normalized source and simulated values in both formats. The calculation is deterministic: it linearizes sRGB, applies a fixed Brettel-Vienot-Mollon projection matrix, clamps the result to the displayable gamut, and encodes it back to eight-bit sRGB. It is useful for repeatable design reviews, automated token checks, documentation, and educational demonstrations, while remaining a simulation rather than a medical assessment.
Use the simulator to inspect a specific interface color
Start with the exact sRGB value used by your design system, stylesheet, chart, or exported asset. The input may be a three-digit or six-digit hexadecimal color, a CSS-style rgb() expression, or three comma-separated integer channels. The response includes a normalized source color as well as the simulated hex and RGB values, so it can move directly into a design note, test fixture, or comparison tool. Treat the transformed swatch as evidence about appearance, not as a pass or fail accessibility verdict. Protanopia can make colors that differ strongly for many viewers appear closer, but usability also depends on contrast, size, surrounding colors, labels, patterns, and interaction states. A red warning and green confirmation should therefore have distinct text or icons even if this simulation suggests an obvious visual difference. For systematic review, run each semantic token separately and compare related states under the same method. Keeping the method fixed matters: mixing outputs from unrelated simulation formulas can create apparent differences caused by the tools rather than by the colors themselves.
Understand the deterministic color pipeline
The calculation begins by validating and normalizing the supplied color into three eight-bit sRGB channels. Those stored channel values are gamma encoded, so the simulator first converts them to linear-light values. It then multiplies the linear triplet by a fixed three-by-three projection associated with the Brettel, Vienot, and Mollon approach to dichromatic color-vision simulation. Matrix multiplication can produce values outside the displayable sRGB interval, especially for highly saturated inputs. Each projected channel is therefore clamped to the closed interval from zero to one before the standard sRGB encoding function is applied. Finally, the encoded values are rounded to the nearest integer and formatted as RGB and lowercase hexadecimal output. Every step is bounded and uses no network request, random value, clock, user profile, or hidden adaptive setting. The same valid input consequently produces the same JSON result. This reproducibility makes the endpoint suitable for snapshots and regression checks. It also makes the method explicit: a different color space, gamut-mapping policy, severity model, or matrix may legitimately produce a different result and should be documented as a different simulation.
Interpret results responsibly in accessibility work
Use the result as one lens in a broader review. A protanopia simulation can reveal that a red series and a dark green series converge, that a destructive button loses its expected emphasis, or that status chips depend too heavily on hue. When that happens, improve the original interface rather than attempting to optimize only the simulated hex value. Add redundant cues such as labels, icons, line styles, shapes, borders, or spatial separation, and verify text and component contrast using the accessibility standard relevant to your product. Test complete states, including hover, focus, disabled, selected, error, and success appearances, because a palette that works in a static legend may fail during interaction. The simulator models a color transformation, not the variation among individuals, displays, ambient conditions, or viewing contexts. It does not measure visual acuity, diagnose protanopia, predict personal perception, or certify compliance. Human evaluation remains valuable for consequential products. In automated workflows, store the source color, simulated output, named method, and the decision made from the review; that audit trail prevents a transformed swatch from being mistaken later for an original brand token.
What you can do with it
Review design tokens
Transform warning, success, accent, and chart tokens with one stable method before a design-system release.
Check data visualizations
Compare simulated series colors and add labels, patterns, or markers where hue alone no longer separates them.
Create regression fixtures
Store deterministic simulated RGB values in tests so later palette changes receive a focused review.
FAQ
What does one simulation cost?
One API request costs $0.002. The calculation processes one color as one item.
Which inputs are accepted?
Use #RGB, #RRGGBB, rgb(r, g, b), or three comma-separated integer channels. RGB channels must be from 0 through 255.
Why is sRGB linearized first?
The matrix represents a linear-light transformation. Applying it directly to gamma-encoded display bytes would perform different arithmetic and produce misleading results.
Does this certify accessibility?
No. It simulates one color transformation. Accessibility also depends on contrast, context, redundant cues, interaction states, and applicable requirements.
Is this a medical test?
No. It neither diagnoses protanopia nor predicts the perception of a particular person. It is a deterministic design and engineering aid.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/color/sim-protanopia \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color":"#e63946"}'const res = await fetch("https://api.kit.forhosting.com/color/sim-protanopia", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color": "#e63946"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/sim-protanopia",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color": "#e63946"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/sim-protanopia", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color":"#e63946"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color":"#e63946"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/sim-protanopia", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"color": "#e63946"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.sim_protanopia",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |