Torii Image Translator API
Bring Torii's image translation, OCR, inpainting, typesetting and colorization into your own apps, paid for with the same credits as the rest of Torii.
Get started in minutes
Start translating images with just a few lines of code.
-
1
Sign up and get your key
Create a free account, then create an API key at the bottom of this page.
-
2
Top up your credits
The API spends the same credits as the rest of Torii. Top up your account to start translating.
-
3
Make your first request
Call the endpoints to translate, run OCR, inpaint, typeset or colorize. Each has example code below.
Limits and rate throttling
Every API key is rate limited, and uploads have size limits, so requests stay fast for everyone.
Standard rate limit
Your API key has a default throttling limit configured to manage steady traffic:
Image and file limits
Uploaded images have to fit these limits, which keeps processing fast:
Handling limit errors
Past the rate limit, requests are rejected with 429 Too Many Requests or 503 Service Unavailable. Past a size limit, they get a validation error. Retry with exponential backoff, so your app handles these gracefully.
API reference
Pick an endpoint to see its parameters, responses and example code.
Typeset endpoint
Render multiple textboxes onto a pre-cleaned image with custom fonts, colors, and alignments.
Credits cost
Each request to the typeset endpoint costs 0.02 credits, scaling up with size to at most 0.1 credits: 0.02 for every 4,000 characters of text or 4 megapixels of image, whichever is larger. A request can have up to 500 text boxes, 5,000 characters per box and 20,000 in total. Boxes must be on or near the image, and together they can cover it at most 4 times, a rotated box counting the area it spans.
Build your request
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
form dataSend these as multipart/form-data fields. Booleans are the strings true and false; anything other than true counts as false.
file
file
required
The image to draw on. Coordinates are in its stored pixels, and EXIF rotation is ignored. Up to 100,000 px on its longest side and 100 megapixels.
text_boxes
string (JSON array)
required
The text boxes to draw, as a JSON array of objects.
- Limit
- 500 boxes and 20,000 characters in total
Each object takes these fields:
text
string
required
The text to draw.
- Limit
- 5,000 characters
x · y · width · height
number
required unless polygon is set
The box's top-left corner and size, in pixels. Width and height must be above 0.
polygon
array
optional
Four [x, y] corners of a rotated or skewed box, such as [[10,10],[210,20],[205,80],[5,70]]. Replaces x, y, width and height, and must enclose an area.
alignment
string
optional
How lines line up inside the box.
- Default
center- Values
leftcenterright
text_color
string
optional
The text colour, as a hex code.
- Default
#ffffff
stroke_color
string
optional
The outline colour, as a hex code.
- Default
#000000
fontsize
integer
optional
The font size to start from, in pixels. Torii shrinks the text until it fits the box.
- Default
- half the image height
- Range
- 1 to 1000
angle
number
optional
The rotation, in degrees. Vertical text needs 90 to stand straight.
- Default
0
direction
string
optional
The writing direction.
- Default
un, which picks a direction for you- Values
left_to_righttop_to_bottomvertical; needs Japanese or Chinese text of 2 or more characters
source_lang
string
optional
The language code of the text, which picks the right letterforms.
- Default
- detected from the text
font
string
optional
The font for every box. Pick one that covers your text's language.
- Default
noto
All fonts
min_font_size
integer
optional
The smallest font size, in pixels, that Torii may shrink text to so it fits. A value outside the range falls back to the default.
- Default
6- Range
- 6 to 100
stroke_disabled
boolean
optional
Turns off the outline on every box.
- Default
false
Response headers
success boolean
Whether the typeset operation was successful.
credits number
The amount of credits remaining.
Response body
The response content is a JSON object.
{
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII+..."
}
Example code
Translate endpoint
Translate images or raw text between dozens of languages. Image translation automatically handles text detection, inpainting and typesetting, with lots of other settings and features available.
Credits cost
Each request to the translate endpoint costs at least 1 credit, but it may cost more depending on the chosen translation model, context and input/output character length.
Build your request
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
form dataSend these as multipart/form-data fields, with the image under file. Booleans are the strings true and false; anything other than true counts as false.
file
file
required
The image to translate, up to 50 MB, 100,000 px on its longest side and 100 megapixels.
target_lang
string
required
The language to translate into, as a language code.
All language codes
translator
string
optional
The model that translates. An unknown value falls back to the default.
- Default
gemini-3.1-flash-lite
All models
reasoning_effort
string
optional
How much the model thinks before it translates. More thinking can help with hard pages, but it uses more tokens, so it costs more credits. Some models always think a little, even with none. An unknown value falls back to the default.
- Default
none- Values
nonelowmediumhigh
font
string
optional
The font for the translated text. Pick one that covers your target language. An unknown value falls back to the default.
- Default
wildwords
All fonts
text_align
string
optional
How translated lines line up inside their bubble.
- Default
auto, which follows the alignment of each original text- Values
autoleftcenterright
min_font_size
integer
optional
The smallest font size, in pixels, that Torii may shrink text to so it fits. A value outside the range falls back to the default.
- Default
6- Range
- 6 to 100
stroke_disabled
boolean
optional
Turns off the outline drawn around text. Torii matches each text's outline and colours to the original, which can look wrong on documents.
- Default
false
bubbles_only
boolean
optional
Translates only text inside speech bubbles, plus long text read with high confidence outside them. Sound effects and background text stay as they are.
- Default
false
source_langs_whitelist
string (JSON array)
optional
Translates and erases only text detected in these languages, such as ["ja", "zh"]. Text in any other language stays as it is, and text whose language can't be detected is always kept. Use the same codes as target_lang.
- Default
- every language
custom_prompt
string
optional
Extra instructions for the model, such as a tone or how to translate certain names.
- Limit
- 2,000 characters
context
string
optional
Background that helps the translation: names, characters, events, earlier dialogue. To chain pages, send None with the first one, then send back the context each response returns. Any other text is used as plain background.
- Limit
- 10,000 characters; only the last 10,000 are kept
x-byok-<provider>
string
optional
Your own API key for an AI provider (BYOK). The translation then runs on your account with that provider, and Torii charges a flat 1 credit per image, or 0.1 per text request. Put the provider's name in place of <provider>.
- Values
x-byok-openrouterOpenRouterx-byok-openaiOpenAIx-byok-googleGoogle Geminix-byok-anthropicAnthropic Claudex-byok-deepseekDeepSeekx-byok-xaixAI Grokx-byok-localYour self-hosted model's key, if it needs one; seex-byok-local-url
x-byok-local-url
string
required for a self-hosted model
The base URL of your self-hosted, OpenAI-compatible endpoint, such as https://my-llm-server.com/v1. Set translator to the model name it serves. Local and private network addresses are refused, so expose it through a tunnel.
x-byok-fallback
boolean
optional
What happens when your own key fails, for example when the model blocks the content or times out. With true, Torii's own models translate the request instead and charge their usual credits, and metadata.fallback_model names the model that ran. With false, the request fails with your provider's error.
- Default
false
Response headers
success boolean
Whether the request was successful. If true, the response contains the translated or cleaned image, else the response contains an error message.
credits number
The amount of credits remaining in the account.
Response body
The response content is a JSON object containing the translated image as a Data URL, the
inpainted image as a Data URL, the detected text objects, remaining account balance, and
request execution metadata. The context
key will be empty if a context chain has not been started (see above for explanation).
{
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII...",
"inpainted": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII...",
"context": "...",
"text": [
{
"x": 623.0,
"y": 326.5,
"width": 50.0,
"height": 141.0,
"text": "Tanjiro",
"originalText": "炭治郎",
"textAlign": "center",
"strokeColor": "#f9f7f9",
"lineWidth": 10,
"fillColor": "#0e0c0f",
"font": "36px WildWords",
"addFontBackground": false,
"addFontBorder": false,
"addBackgroundColor": "#ffffff",
"rotation": 0.0,
"angle": 0.0,
"layout": "h",
"textDir": "ltr"
}
],
"metadata": {
"credits_used": 1.25,
"ocr_time": 0.452,
"inpaint_time": 0.381,
"translation_time": 1.124,
"render_time": 0.089,
"total_texts_count": 14,
"filtered_texts_count": 0,
"prompt_tokens": 420,
"completion_tokens": 150,
"reasoning_tokens": 0,
"total_tokens": 570,
"attempts": [
{
"model": "google/gemini-3.1-flash-lite",
"duration": 1.124,
"status": "success",
"stage": "translation"
}
]
}
}
{
"text": [
"Translated sentence one.",
"Translated sentence two.",
"Translated paragraph three."
],
"detected_lang": "ja",
"metadata": {
"credits_used": 0.25,
"translation_time": 0.854,
"total_texts_count": 3,
"filtered_texts_count": 0,
"prompt_tokens": 120,
"completion_tokens": 45,
"reasoning_tokens": 0,
"total_tokens": 165,
"attempts": [
{
"model": "google/gemini-3.1-flash-lite",
"duration": 0.854,
"status": "success",
"stage": "translation"
}
]
},
"context": "..."
}
Response fields
image string
The base64-encoded Data URL of the final translated image. Only present for image translation requests (DataType: IMAGE).
inpainted string
The base64-encoded Data URL of the inpainted image (image with source text removed). Only present for image translation requests (DataType: IMAGE).
original string
Optional. The base64-encoded Data URL of the original source image. Only present for image translation requests (DataType: IMAGE) when a remote image URL is supplied and the user is authenticated.
context string
Optional. The updated translation context string. Only present if a context chain is active or has been updated.
detected_lang string
The detected ISO language code of the input text (e.g. "ja", "ko", "zh"). Only present for text translation requests (DataType: TEXT).
text array
An array of translated contents. Always present. For image responses, this is an array of objects detailing bounding box coordinates and styling rules. For text responses, this is an array of raw translated strings.
text[].x / y number
The X and Y pixel coordinates of the center point of the text bounding box.
text[].width / height number
The dimensions (width and height) of the text box in pixels.
text[].text string
The final translated text content rendered inside the box.
text[].originalText string
The original detected source text.
text[].textAlign string
Text alignment style ("left", "center", "right").
text[].fillColor / strokeColor string
The text fill and outline/stroke colors in hexadecimal format (e.g. #ffffff).
text[].lineWidth number
The width of the text stroke/outline border in pixels.
text[].font string
CSS font property value specifying size and family (e.g. "36px WildWords").
text[].addFontBackground / addFontBorder boolean
Options indicating whether extra background fills or custom border outlines are applied behind/around the font.
text[].addBackgroundColor string
Hexadecimal background color for the text background if enabled.
text[].rotation / angle number
The text block's rotation in radians and degrees, respectively.
text[].layout string
The orientation layout direction of the text block ("h" for horizontal, "v" for vertical).
text[].textDir string
The layout reading direction of the text flow ("ltr" for left-to-right, "rtl" for right-to-left).
metadata object
Execution metrics, stage timings, token consumption, reasoning thoughts, and fallback attempt waterfall.
metadata.credits_used number
The exact amount of credits deducted for the request.
metadata.ocr_time number
Duration of the OCR text detection stage in seconds.
metadata.inpaint_time number
Duration of the text removal/inpainting stage in seconds.
metadata.translation_time number
Total duration of translation attempts in seconds.
metadata.summarization_time number
Optional. Total duration of context summarization attempts in seconds (when context summarization runs).
metadata.render_time number
Duration of text rendering and font typesetting in seconds.
metadata.total_texts_count number
Total number of detected text paragraphs/bubbles.
metadata.filtered_texts_count number
Number of text paragraphs filtered out by the source languages whitelist.
metadata.prompt_tokens number
Input prompt tokens consumed across all successful LLM calls.
metadata.completion_tokens number
Output completion tokens generated across all successful LLM calls.
metadata.reasoning_tokens number
Thinking/reasoning tokens generated by reasoning models.
metadata.total_tokens number
Total tokens consumed across all successful LLM calls.
metadata.reasoning string
Optional. The internal thinking/reasoning process returned by the translation model.
metadata.fallback_model string
Optional. The fallback model that completed the translation if the primary model failed.
metadata.fallback_reason string
Optional. The reason the primary model failed and triggered a fallback (e.g. "content_filter", "timeout", "schema_validation_failed").
metadata.attempts array
An array of objects representing each model attempt and fallback in the execution waterfall.
metadata.attempts[].model string
Model identifier used for this attempt.
metadata.attempts[].duration number
Duration of this attempt in seconds.
metadata.attempts[].status string
Status of the attempt ("success" or "failed").
metadata.attempts[].stage string
Pipeline stage ("translation" or "summarization").
metadata.attempts[].reason string
Optional. The reason the attempt failed if status is "failed".
Example code
OCR endpoint
A powerful OCR endpoint that returns highly detailed information, including text orientation, font sizes, and extracted colors (text, background, stroke) for each paragraph.
Credits cost
Each request to the ocr endpoint costs 1 credit.
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
form dataSend the image as a multipart/form-data field named file, or send its raw bytes as the request body with Content-Type: application/octet-stream.
file
file
required
The image to read, from 50 × 50 px up to 100,000 px on its longest side and 100 megapixels.
Response headers
success boolean
Whether the request was successful. If true, the response contains the OCR result, else the response contains an error message.
credits number
The amount of credits remaining in the account.
Response body
The response content is a JSON array of detailed paragraph objects.
[
{
"text": "Thank you very much!",
"polygon": [[10, 320], [170, 320], [170, 370], [10, 370]],
"fontsize": 24,
"angle": 0.0,
"alignment": "center",
"direction": "left_to_right",
"bg_color": [255, 255, 255],
"text_color": [0, 0, 0],
"stroke_color": [0, 0, 0],
"has_dominant_bg_color": true,
"confidence": 0.998,
"language_details": {
"language": "ENGLISH",
"code": "en",
"confidence": 0.999
},
"removed": false,
"lines": [
{
"text": "Thank you",
"polygon": [[11, 326], [165, 327], [165, 361], [11, 360]],
"confidence": 0.998,
"angle": 0.0,
"direction": "left_to_right",
"language_details": {
"language": "ENGLISH",
"code": "en",
"confidence": 0.999
},
"removed": false,
"words": [
{
"text": "Thank",
"polygon": [[12, 327], [100, 327], [99, 361], [11, 360]],
"confidence": 0.998,
"direction": "left_to_right",
"symbols": [
{
"text": "T",
"polygon": [[12, 327], [25, 327], [25, 361], [12, 361]],
"confidence": 0.999
}
]
}
]
}
]
}
]
Response fields
paragraph array
The root response is an array of objects, where each object represents a detected paragraph of text.
paragraph[].text string
The full recognized text content of the paragraph.
paragraph[].polygon array
A list of 4 [x, y] points defining the oriented bounding box of the paragraph.
paragraph[].fontsize number
The estimated median font size of the text in pixels.
paragraph[].angle number
The rotation angle of the paragraph in degrees (0-360).
paragraph[].alignment string
The text alignment within the paragraph ("left", "center", "right").
paragraph[].direction string
The text flow direction of the paragraph (e.g., "left_to_right", "top_to_bottom").
paragraph[].bg_color / text_color / stroke_color array
The detected colors in [B, G, R] format.
paragraph[].language_details object
Detailed language detection results.
paragraph[].language_details.language string
The full name of the detected language (e.g., "ENGLISH", "JAPANESE").
paragraph[].language_details.code string
The ISO 639-1 language code (e.g., "en", "ja").
paragraph[].language_details.confidence number
The confidence score of the language detection (0 to 1).
paragraph[].removed boolean
Indicates if the paragraph was filtered out (e.g., detected as noise or furigana).
paragraph[].confidence number
The average confidence score of the recognition (0 to 1).
paragraph[].lines array
An array of detailed line objects within the paragraph.
paragraph[].lines[].direction string
The text flow direction (e.g., "left_to_right", "top_to_bottom").
paragraph[].lines[].language_details object
Detailed language detection for this specific line.
paragraph[].lines[].language_details.language string
Full name of the line-level language.
paragraph[].lines[].language_details.code string
ISO 639-1 code for the line.
paragraph[].lines[].language_details.confidence number
Detection confidence for the line.
paragraph[].lines[].removed boolean
Mainly used for detected furigana (small reading aids for Kanji).
paragraph[].lines[].words array
An array of word objects within the line.
paragraph[].lines[].words[].polygon array
A list of 4 [x, y] points defining the word's bounding box.
paragraph[].lines[].words[].symbols array
An array of individual character/symbol objects.
paragraph[].lines[].words[].symbols[].text string
The recognized character.
paragraph[].lines[].words[].symbols[].polygon array
A list of 4 [x, y] points defining the symbol's bounding box.
paragraph[].lines[].words[].symbols[].confidence number
The recognition confidence for this specific character.
Example code
Inpaint endpoint
Remove text or objects from images. Returns a clean image with the masked areas filled in by Torii's inpainting model.
Credits cost
Each request to the inpaint endpoint costs 0.02 credits.
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
form dataSend both images as multipart/form-data fields.
image
file
required
The image to clean, up to 100,000 px on its longest side and 100 megapixels.
mask
file
required
A black-and-white image the same size as image. Every pixel that isn't black marks an area to erase and fill in.
Response headers
success boolean
Whether the request was successful.
credits number
The amount of credits remaining.
Response body
The response content is a JSON object.
{
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=..."
}
Example code
Colorize endpoint
Add color to a black-and-white image, using the model you pick. Returns a JPEG the same size as your upload.
Credits cost
Each image costs at least the credits listed under colorize_model, or a flat
1 credit with your own provider key (BYOK). metadata.credits_used reports what
each request cost.
Failed and refused requests cost nothing, with one exception: without your own key, images Grok blocks still cost credits, because xAI bills for them.
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
form dataSend these as multipart/form-data.
image
file
required
The black-and-white image to color.
- Limit
- 10,000 px on its longest side, and the long side at most 3 times the short side
colorize_model
string
optional
The model that colors the image, with its credits per image.
- Values
localTorii's own model, 1 credit. It runs on Torii's servers, so no provider's content filter applies.museMeta Muse Image, 12 creditsgptOpenAI GPT Image 2, 16 creditsgrokxAI Grok Imagine, 25 creditsgeminiGoogle Nano Banana 2.1, 46 credits- Default
muse
colorize_prompt
string
optional
Extra instructions for the model, such as a character's hair color. local ignores it.
- Limit
- 2,100 characters; anything longer is cut off
x-byok-<provider>
string
optional
Your own API key for the model's provider (BYOK). The image then runs on your account with that provider, and Torii charges a flat 1 credit. local takes no key.
- Values
x-byok-openrouterFormuseandgptx-byok-xaiForgrokx-byok-googleForgemini
Response headers
success boolean
Whether the request was successful. If false, the body is a plain-text message saying why.
credits number
The amount of credits remaining.
Response body
The response content is a JSON object.
{
"success": true,
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL...",
"credits": 988,
"metadata": {
"credits_used": 12,
"colorize_time": 6.412,
"colorize_model": "muse"
}
}
image string
The colored image as a base64-encoded JPEG Data URL, the same size as your upload.
credits number
The amount of credits remaining.
metadata.credits_used number
The credits this request cost.
metadata.colorize_time number
How long the model took, in seconds.
metadata.colorize_model string
The model that colored the image.
Errors
A failed request sets success to false, with a reason such as an image past the
limits, too few credits for the model, or a model refusing it. local colors one image at a time across all
users and answers busy if it can't start within a couple of seconds, so retry those
after a short delay.
Example code
Credits endpoint
Retrieve the current credit balance remaining in your account.
Credits cost
Requests to the credits endpoints are completely free.
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token.
Parameters
This endpoint takes no parameters.
Response headers
success boolean
Whether the request was successful.
Response body
The response content is a JSON object.
{
"credits": 145.25
}
Example code
Usage endpoint
Keys endpoint
Retrieve the per-day request counts shown in your dashboard, broken down by endpoint, for one API key, all your keys together, or your whole account.
Credits cost
Requests to the usage and keys endpoints are completely free and are not counted as usage.
Authentication
Authenticate your requests by including your API key in the Authorization
header as a Bearer token. Any of your keys can read the usage of every key on your account.
Parameters
query stringSend these in the query string, such as ?days=90&scope=api.
days
integer
optional
How many days to return, ending today (UTC).
- Default
30- Range
- 1 to 730
scope
string
optional
What the counts cover.
- Default
key- Values
keyOne key: the one making the request, or the one inkey_idapiEvery key on your account added together, revoked ones includedaccountEverything on your account: the website, extension and apps as well as the API
key_id
string
optional
Reads another key on your account instead of the one making the request, including a revoked one. Find ids with the keys endpoint, or next to each key at the bottom of this page. Works only with scope key, which it sets for you.
- Format
- 16 hex characters
by_key
boolean
optional
Also splits the totals and each day by key, under by_key. Works only with scope api.
- Default
false
Response headers
success boolean
Whether the request was successful.
Response body
The response content is a JSON object. With scope key
or api,
each count is one successful request, under the endpoint it was sent to. With scope
account,
each step counts on its own, so one translated image adds an OCR and a translation, and an
api
block counts the steps that came through the API. The byok
counts are the subset of those requests that ran on your own provider key rather than
Torii's; a BYOK request that fell back to Torii's model is not counted as BYOK. The credits
block holds the credits those requests spent, by endpoint.
scope string
The scope the counts cover.
key object · keys array
With scope
key,
the key the counts are for. With scope api,
every key on your account. Each one has the fields the keys endpoint returns.
totals object
Request counts summed over
the whole period. With by_key,
its by_key
holds the same counts for each key id that was used in the period.
usage array
One entry per day, oldest
first, with the same counts as totals
plus its date
(YYYY-MM-DD, UTC). With by_key,
each day's by_key
holds only the keys used that day.
{
"scope": "api",
"keys": [
{ "id": "3f9a1c2b7d4e5f60", "name": "Discord bot", "active": true, ... },
{ "id": "8b02e47c19d3a6f5", "name": "Old server", "active": false, ... }
],
"totals": {
"translate": 120, "ocr": 40, "inpaint": 15, "typeset": 0, "colorize": 0, "total": 175,
"byok": { "translate": 100, "ocr": 0, "inpaint": 5, "typeset": 0, "colorize": 0, "total": 105 },
"credits": { "translate": 21.5, "ocr": 40, "inpaint": 0.3, "typeset": 0, "colorize": 0, "total": 61.8 }
},
"usage": [
{
"date": "2026-09-24",
"translate": 12, "ocr": 4, "inpaint": 1, "typeset": 0, "colorize": 0, "total": 17,
"byok": { "translate": 10, "ocr": 0, "inpaint": 1, "typeset": 0, "colorize": 0, "total": 11 },
"credits": { "translate": 2.4, "ocr": 4, "inpaint": 0.02, "typeset": 0, "colorize": 0, "total": 6.42 }
},
...
]
}
Example code
Manage your API keys
Give each app its own key. You'll see what each one uses, and you can revoke one without touching the others.
Sign in to create and manage your API keys.
Sign inKeep your keys secret and never share them publicly. A key is shown only once, when you create it.