Recognition API
POST https://api.ninetile.io/v1/recognize accepts one challenge and returns an answer synchronously. It does not return a token. An answered request is charged at $0.30 per 1,000 answers; a puzzle that cannot be answered returns 422 recognition_failed without a charge.
Simple grid and area-select form
type:hcaptchafor a grid orhcaptcha_area_selectfor a point challenge.task: English instruction, nonempty and at most 500 characters.image_dataorimage_urls: images in task order. Grid accepts 1–27 images; area-select accepts exactly one.image_examples(optional): 1–3 reference images.
Images may be bare base64 or a base64 data URI. URLs must be HTTPS on hcaptcha.com or a subdomain; arbitrary URLs are not fetched. PNG, JPEG, GIF and WebP are supported. Each image is limited to 1.5 MiB and 1 megapixel; all images together are limited to 12 megapixels and the request to 12 MiB.
{
"type": "hcaptcha",
"task": "Select all bicycles",
"image_data": ["<BASE64_IMAGE_1>", "<BASE64_IMAGE_2>"]
}
Send this JSON to https://api.ninetile.io/v1/recognize with an API key and JSON content type. The placeholders must be replaced with actual image data.
Full challenge form
Use {"data": {...}} for the full challenge object. data.request_type is one of:
image_label_binary: up to 27 tasks.image_label_area_select: up to 5 tasks.image_drag_drop: up to 5 tasks; each drag task needs anentitiesarray.
data.requester_question.en must contain the instruction. Each data.tasklist item needs a nonempty task_key and datapoint_uri. Drag entities use entity_uri; keep the challenge's entity identifiers intact. Image restrictions also apply to these fields.
Answer shapes
For a simple grid, data is a boolean for each tile in the same order. For simple area select, data contains x, y, w: 0, and h: 0, with points listing all click positions. Coordinates are percentages of image dimensions. Drag answers contain each entity ID and its box in percentage coordinates; the drop centre is (x + w/2, y + h/2). The full challenge form returns answers grouped by task.
Responses also include an id and charged_usd. Optionally report {"id":"rec_...","result":"solved"} or "failed" to POST /v1/recognize/outcome; reporting an outcome does not change billing. Video challenges are not accepted by the HTTP Recognition API.
Illustrative responses
A simple grid response preserves input order:
{"id":"rec_example","data":[true,false],"charged_usd":0.0003}
For an area task, a response may include:
{"id":"rec_example","data":{"x":25,"y":60,"w":0,"h":0},"points":[{"x":25,"y":60}],"charged_usd":0.0003}
These IDs and coordinates are examples, not actual solutions. Full-form area responses contain one data entry and one points list per task. A full grid response groups boolean answers by page. Drag results preserve the predictor's boxes and entity identifiers. An outcome report returns id, result and refunded_usd: 0.
Full-form request structure
{"data":{"request_type":"image_label_binary","requester_question":{"en":"Select all bicycles"},"tasklist":[{"task_key":"task-1","datapoint_uri":"<BASE64_IMAGE>"}]}}
This is a structural example; replace the placeholder with real image data. For drag tasks use image_drag_drop and provide each task's entities array with entity image URIs and identifiers. Do not substitute a made-up entity ID for the challenge's ID.