AnvilJSON utilities

Anvil › Docs › /v1/color

Colour API: hex to RGB, HSL and OKLCH, plus WCAG contrast check

Give a hex colour and get it back in the formats designers and CSS use, plus its relative luminance. Add a second colour and you also get the WCAG 2 contrast ratio and whether it passes AA and AAA for normal and large text.

In one line: GET /v1/color?hex=1f6f5c&against=ffffff returns JSON. No key, CORS on, 60 requests a minute.
GET

/v1/color

Colour formats (hex, RGB, HSL, OKLCH) and WCAG contrast. Change the values and press Send request to call the live API.

Parameters

NameTypeWhat it doesDefault
hex requiredstringColour like 1f6f5c or #fff (encode # as %23)—
againststringSecond colour for a contrast check—

Example

Request:

GET https://api.oddlathe.com/v1/color?hex=1f6f5c&against=ffffff

Response (generated by the real code when these docs were last built):

{
 "hex": "#1f6f5c",
 "rgb": {
  "r": 31,
  "g": 111,
  "b": 92,
  "css": "rgb(31 111 92)"
 },
 "hsl": {
  "h": 166,
  "s": 56,
  "l": 28,
  "css": "hsl(166 56% 28%)"
 },
 "oklch": {
  "l": 0.4888,
  "c": 0.0819,
  "h": 173.5,
  "css": "oklch(48.9% 0.082 173.5)"
 },
 "relative_luminance": 0.1243,
 "best_text": "#ffffff",
 "contrast": {
  "against": "#ffffff",
  "ratio": 6.02,
  "aa_normal": true,
  "aa_large": true,
  "aaa_normal": false,
  "aaa_large": true
 }
}

Code examples

curl
curl 'https://api.oddlathe.com/v1/color?hex=1f6f5c&against=ffffff'
JavaScript (browser or Node 18+)
const params = new URLSearchParams({
  hex: "1f6f5c",
  against: "ffffff"
});
const res = await fetch(`https://api.oddlathe.com/v1/color?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);
Python (standard library only)
import json, urllib.parse, urllib.request

params = urllib.parse.urlencode({"hex": "1f6f5c", "against": "ffffff"})
url = "https://api.oddlathe.com/v1/color?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
    data = json.load(r)
print(data)

When it's useful

  • Checking brand colours for accessible text before a release
  • Design token pipelines that need OKLCH values
  • Automated contrast checks in CI

Good to know

  • Accepts 3- or 6-digit hex with or without #. Encode # in a URL as %23, or just leave it out.
  • WCAG 2 contrast is (L1 + 0.05) / (L2 + 0.05). AA needs 4.5:1 for normal text and 3:1 for large text (24 px, or 18.66 px bold); AAA needs 7:1 and 4.5:1.
  • The ratio is shown rounded to two decimals, but the pass/fail flags use the exact value, so a ratio of 4.497 displays as 4.5 and still fails AA. best_text tells you whether black or white text reads better on the colour.

Contrast uses the WCAG 2 relative-luminance formula; AA needs 4.5:1 for body text and 3:1 for large text, AAA needs 7:1 and 4.5:1.

Errors

Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:

  • missing_param (400): a required parameter is missing or empty
  • bad_param (400): a value is the wrong type or out of range (the message says which)
  • rate_limited (429): over 60 requests a minute; wait for Retry-After seconds

Questions

Why does my brand colour fail on white?

Mid-tone colours like many greens and oranges sit near 3:1 against white. Darken them for body text, or keep them for large headings and icons.

What is OKLCH?

A newer way of describing colour by lightness, chroma and hue that matches how bright colours actually look, which makes it good for building even tint scales.

Related endpoints

Prefer a page to an API?

Published , updated · OpenAPI 3.1 spec · Limits and privacy