TIA: Text in Image AccessibilityBeta

Documentation

HTTP API

Send an image, get back a JSON report: each text region TIA found, its contrast ratio, and a WCAG verdict. No sign-in and no API key.

Endpoint

POST https://tia.dohunkim.xyz/api/audit

The body is multipart/form-data. The response is always JSON, with cache-control: no-store.

Request

FieldRequiredDescription
imageYesThe image file: PNG, JPEG, or WebP, up to about 4 MB and 4 megapixels. Send it as a file part with an image content type.
levelNoAA or AAA. Defaults to AA. Sets the ratio each region must reach.

Examples

curl

curl example
curl -X POST https://tia.dohunkim.xyz/api/audit \
  -F "image=@banner.png" \
  -F "level=AA"

Python (requests)

Python example
import requests

with open("banner.png", "rb") as f:
    r = requests.post(
        "https://tia.dohunkim.xyz/api/audit",
        files={"image": ("banner.png", f, "image/png")},
        data={"level": "AA"},
        timeout=90,
    )

if r.ok:
    report = r.json()
    for region in report["regions"]:
        print(region["verdict"], region["contrast_ratio"], region["text"])
else:
    print(r.status_code, r.json()["detail"])

JavaScript (fetch)

JavaScript example
// Browser or Node 18+. In the browser, take the file from an <input type="file">.
const form = new FormData();
form.append("image", file);      // a File or Blob
form.append("level", "AA");

const res = await fetch("https://tia.dohunkim.xyz/api/audit", { method: "POST", body: form });
const body = await res.json();

if (!res.ok) throw new Error(body.detail);
console.log(body.summary);       // { regions, passing, failing, review }

The first request after a quiet period can take up to a minute while the service starts. Set a generous timeout (60 to 90 seconds) and retry once on a 503.

Response

A successful check returns 200 with this shape. The example is shortened (...) and its values are illustrative.

Example response
{
  "image": { "width": 1200, "height": 630 },
  "level": "AA",
  "summary": { "regions": 3, "passing": 1, "failing": 1, "review": 1 },
  "regions": [
    {
      "id": 0,
      "location": { "x": 96, "y": 120, "width": 520, "height": 140 },
      "text": "Spring sale starts today",
      "verdict": "fail",
      "contrast_ratio": 1.5,
      "required_ratio": 3,
      "text_size": "large",
      "low_vision": [
        { "reader": "20/20", "reading": "difficult" },
        { "reader": "20/40", "reading": "unreadable" },
        { "reader": "20/80", "reading": "unreadable" },
        { "reader": "20/200", "reading": "unreadable" }
      ],
      "guidance": "TIA reads this at about 1.5:1; WCAG AA needs 3:1 for large text. ..."
    },
    {
      "id": 1,
      "location": { "x": 96, "y": 300, "width": 610, "height": 36 },
      "text": "Free delivery on every order this week",
      "verdict": "pass",
      "contrast_ratio": 12.7,
      "required_ratio": 4.5,
      "text_size": "normal",
      "low_vision": [ ... ],
      "guidance": "Meets WCAG AA contrast for normal text (12.7:1, needs 4.5:1 or more)."
    },
    {
      "id": 2,
      "location": { "x": 96, "y": 400, "width": 180, "height": 44 },
      "text": "Shop the sale",
      "verdict": "review",
      "contrast_ratio": 4.9,
      "required_ratio": 4.5,
      "text_size": "normal",
      "low_vision": null,
      "guidance": "Couldn't measure this region confidently, so please check it by hand. ..."
    }
  ],
  "notes": [
    "Each text region is checked against its own background.",
    "..."
  ],
  "provenance": {
    "basis": "image-pixels",
    "independent": true,
    "disclosure": "Every color in this result was read from the uploaded image's own pixels; ..."
  }
}

Top-level fields

FieldTypeDescription
imageobjectwidth and height of the image as checked, in pixels.
levelstringThe level checked against: AA or AAA.
summaryobjectCounts: regions (text regions found), passing, failing, and review. They are counted from the verdicts in regions.
regionsarrayOne object per text region, described below. Empty if no text was found.
notesarray of stringsPlain-language notes about the whole result, such as what Review means and that this is not a certification. Show them to your users.
provenanceobjectWhere the colors came from. For an uploaded image, basis is "image-pixels" and independent is true: every color was read from the image itself. disclosure says the same in a sentence.

Region fields

FieldTypeDescription
idintegerThe region’s index, from 0. The on-site report numbers regions from 1, so region 0 is shown as 1.
locationobjectThe region’s box in image pixels: x and y of the top-left corner, then width and height.
textstring or nullThe text TIA read in the region, or null if it could not read it. Use it to find the region, not as an exact transcript.
verdictstring"pass", "fail", or "review". Review means TIA could not confirm a pass or a fail; check that region by hand. See Reading a report.
contrast_rationumber or nullThe contrast ratio TIA measured between the text and its background, rounded to one decimal place. null when no ratio could be measured.
required_rationumberThe ratio WCAG asks for at this level and text size: 4.5 (normal) or 3 (large) at AA, 7 (normal) or 4.5 (large) at AAA.
text_sizestring"normal" or "large", in the WCAG sense, as estimated from the image. An image does not say how large it will be shown, so treat this as an estimate.
low_visionarray or nullHow readable the region is likely to be for readers with different visual acuity. Each entry has reader ("20/20", "20/40", "20/80", or "20/200") and reading ("comfortable", "difficult", or "unreadable"). null when TIA could not estimate it. This is guidance beyond WCAG and does not change the verdict.
guidancestringOne or two plain sentences on what the verdict means and what to do next.

TIA is in beta, so new fields may be added. Ignore any field you do not recognize.

Errors

Every error is JSON with one field, detail: a short sentence you can show to a person. Branch on the status code, not on the wording.

StatusWhendetail
400The body is not valid multipart form dataInvalid upload.
400No image file partNo image provided.
400level is not AA or AAAlevel must be AA or AAA.
400The file could not be opened as an imageCould not read that file as an image.
413The request is over about 4.5 MB. The hosting platform refuses it before it reaches TIA, so the body is the platform’s error, not TIA’s JSON.None
413The image is over 4 megapixelsImage resolution too high; please downscale below 4 MP.
415The file part does not have an image content typePlease upload an image file.
429Too many requests from your addressToo many requests. Wait a minute and try again.
500The service could not analyze the image, or the site is misconfiguredCould not analyze that image. or Server not configured.
502The analysis service sent a response the site could not useThe analysis service returned an unexpected response.
503The analysis service is starting or unreachableThe analysis service is starting up or unavailable. Please try again in a moment. or a similar sentence from the service itself

If the service returns another error, the status code is passed through and detail is its short message, or a general sentence such as That request could not be processed. (4xx) or The analysis service had trouble with that image. Please try again. (5xx).

Limits

  • File size: about 4 MB per image. The hosting platform refuses any request over 4.5 MB, so compress or downscale larger files first. For a larger image, use the MCP server with an image URL.
  • Resolution: up to 4 megapixels (for example 2000 by 2000). Downscale larger images first.
  • Rate: about 20 requests per 60 seconds per IP address. This limit is best effort: it is counted in memory on each server instance, so you may be cut off earlier or later than that. The analysis service has its own limit as well. On a 429, wait a minute and retry.
  • Speed: the first check after a quiet period can take up to a minute while the service starts. Later checks are usually much faster.
  • Use: TIA is a free beta with no uptime promise. For large batches, send images one at a time.

Results are an automated aid, not legal advice or a certification of conformance. Before you act on them automatically, read where TIA can be wrong.