W3C brightness difference calculator
Compare two colors with the legacy W3C brightness test: black against white differs by 255, well above the 125 needed to pass. Handy for reproducing old audits; for current accessibility decisions, use a WCAG contrast check. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Color 1
- #000
- Color 2
- #fff
- Color 1
- #000000
- Color 2
- #FFFFFF
- Brightness 1
- 0
- Brightness 2
- 255
The W3C brightness difference calculator compares two hexadecimal colors with the historical perceived-brightness formula associated with the W3C AERT accessibility draft. It converts each color into a weighted brightness value, takes the absolute difference, and reports whether that difference is greater than 125. The result is deterministic and includes normalized colors, both brightness values, the difference, the threshold, and a clear pass or fail. This legacy test can help reproduce old audits and compatibility checks, but it should not replace modern WCAG contrast-ratio evaluation for current accessibility decisions.
What the legacy brightness test measures
The legacy W3C brightness difference test estimates how light or dark each color appears by weighting its red, green, and blue channels differently. Human vision is more sensitive to green than red and more sensitive to red than blue, so the calculation uses 299 for red, 587 for green, and 114 for blue, then divides the sum by 1000. After calculating both perceived-brightness values, this capability takes their absolute difference.
A result greater than 125 passes the historical recommendation; a result of exactly 125 does not pass because the wording requires the difference to be greater than the threshold. The order of the two colors therefore does not affect the outcome. This calculation measures only brightness separation.
It does not calculate the companion legacy color-difference formula, and it does not produce the contrast ratio required by contemporary WCAG success criteria. Use it when you specifically need to reproduce the historical brightness test, compare results with older tools, or maintain a system whose acceptance rule explicitly names this formula. For new accessibility work, treat it as supplementary information rather than a complete compliance decision.
How to enter colors and read the response
Provide each input as hexadecimal RGB notation with a leading number sign. Both the compact three-digit form, such as #0AF, and the full six-digit form, such as #00AAFF, are accepted. Compact values are expanded by repeating each digit, and returned colors are normalized to uppercase six-digit notation.
Alpha channels, named CSS colors, rgb() functions, whitespace, and missing number signs are rejected instead of being guessed. This strict validation keeps repeated calls predictable and prevents a malformed value from silently becoming a different color.
Use the result in audits and automated checks
Store the normalized input colors and the returned difference with the audit record so another reviewer can reproduce the decision without relying on a screenshot or a browser’s color parser. In automated checks, examine passes rather than rebuilding the threshold comparison in every client; the response also exposes the underlying numbers for reporting and diagnostics. A failure means only that the pair does not exceed the legacy brightness threshold.
A pass means only that it does exceed that threshold. Neither outcome proves that text meets a modern WCAG conformance level, because current contrast requirements use relative luminance and a ratio, consider text size and weight, and define different thresholds. If a project must support both historical and current rules, run this calculation as the named legacy check and run a WCAG contrast-ratio check separately.
What you can do with it
Reproduce a legacy accessibility audit
Recalculate a historical brightness-difference result with the exact weighted formula and strict greater-than threshold.
Review archived design systems
Document how older palette decisions performed under the brightness test used when they were created.
FAQ
What formula does this calculator use?
It calculates (299 × red + 587 × green + 114 × blue) / 1000 for each color, then takes the absolute difference.
What value passes the legacy test?
The brightness difference must be greater than 125. A difference equal to 125 fails.
Does a pass mean the colors meet current WCAG contrast requirements?
No. Modern WCAG contrast uses relative luminance and a contrast ratio. This result reproduces a separate legacy test.
Which color formats are accepted?
Use #RGB or #RRGGBB hexadecimal notation. Alpha, CSS color names, rgb() syntax, and surrounding whitespace are not accepted.
Does the order of the colors matter?
No. The calculation uses an absolute difference, so reversing the colors leaves the difference and pass result unchanged.
Related tools
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/brightness-diff-w3c \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color_1":"#000000","color_2":"#FFFFFF"}'const res = await fetch("https://api.kit.forhosting.com/color/brightness-diff-w3c", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color_1": "#000000",
"color_2": "#FFFFFF"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/brightness-diff-w3c",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color_1": "#000000",
"color_2": "#FFFFFF"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/brightness-diff-w3c", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color_1":"#000000","color_2":"#FFFFFF"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color_1":"#000000","color_2":"#FFFFFF"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/brightness-diff-w3c", 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_1": "#000000",
"color_2": "#FFFFFF"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.brightness_diff_w3c",
"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.
Limits
max_color_chars | 7 |
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. |
Technical notes
How to enter colors and read the response
The response lists brightness_1 and brightness_2 on the usual zero-to-255 brightness scale, brightness_difference as their absolute distance, threshold as 125, and passes as a Boolean value. Because the calculation is symmetric, swapping color_1 and color_2 swaps the two individual brightness values but leaves brightness_difference and passes unchanged.
Use the result in audits and automated checks
The API charges $0.002 per request, while the browser implementation uses the same deterministic solver without network access, random values, timestamps, or hidden state.
Integration use cases
Protect regression fixtures
Compare established color pairs in automated tests and detect changes to a legacy acceptance rule.
Technical questions
How much does an API request cost?
Each API request costs $0.002. The browser calculation runs locally with the same deterministic logic.