Image translation API: send an image, get a translated image back

The TranslateMyImage API translates the text inside an image and returns a new image, not a list of strings. You send one image and one target language to a single endpoint; the JSON response contains a URL to the translated image, generated to keep the original layout. This page shows what the API does, request examples in curl, Python and Node.js, how to handle errors, and when building your own OCR pipeline makes more sense. The full reference is in the API documentation.

In short

  • One endpoint: POST https://translatemyimage.com/api/translate with an X-API-Key header and a multipart body containing the image and target_lang.
  • One request = one image into one language = one credit when it completes. Target languages: en, fr, es, de, it, pt, ja, ko, zh.
  • API access starts with the Pro plan (Pro, Premium or Enterprise). Review generated images before you publish them.

Request fields

The body is multipart/form-data, which your HTTP client sets for you.

FieldRequiredAccepted values
fileYesA JPG, PNG or WEBP image, up to 10 MB and 25 megapixels
target_langYesen, fr, es, de, it, pt, ja, ko or zh
source_langNoOne of the nine codes above; omit it or send auto to auto-detect
qualityNobasic (default) or ultra
business_typeNodefault, marketing, edition (the Manga/Comics mode) or technical documentation
custom_promptNoInstructions for the model, up to 1,000 characters (Pro plan and above)

Response

A successful call returns this shape (example from the reference):

{
  "success": true,
  "translation": {
    "id": "clxb1234567890",
    "originalUrl": "https://storage.com/original.jpg",
    "translatedUrl": "https://storage.com/translated.jpg",
    "sourceLang": "fr",
    "targetLang": "en",
    "status": "completed",
    "createdAt": "2026-09-21T15:27:39.000Z",
    "metadata": { "quality": "basic", "model": "muse-image" }
  }
}

sourceLang is null when you omit source_lang or send auto. Errors return JSON with success: false, an error message and, once the key is accepted, a stable code such as insufficient_credits.

Quick start

Create a key on the dashboard's API Keys page. It is shown only once, so store it in an environment variable or a secret manager right away.

curl

curl -X POST https://translatemyimage.com/api/translate \
  -H "X-API-Key: $TMI_API_KEY" \
  -F "[email protected]" \
  -F "target_lang=es" \
  -F "source_lang=auto" \
  -F "business_type=marketing"

Python (requests), with a retry when the image service is rate limited:

import os
import time

import requests

API_URL = "https://translatemyimage.com/api/translate"
API_KEY = os.environ["TMI_API_KEY"]


def translate_image(path, target_lang, business_type="default", max_attempts=5):
    for attempt in range(max_attempts):
        with open(path, "rb") as image:
            response = requests.post(
                API_URL,
                headers={"X-API-Key": API_KEY},
                files={"file": image},
                data={
                    "target_lang": target_lang,
                    "source_lang": "auto",
                    "business_type": business_type,
                },
                timeout=900,  # generation can take minutes: keep this generous
            )
        if response.status_code == 429:
            time.sleep(2 ** attempt)  # exponential backoff, then retry
            continue
        payload = response.json()
        if response.status_code != 200 or not payload.get("success"):
            raise RuntimeError(f"{response.status_code}: {payload.get('error')}")
        return payload["translation"]
    raise RuntimeError(f"Still rate limited after {max_attempts} attempts")


for lang in ["es", "fr", "de"]:
    result = translate_image("product-front.jpg", lang, "marketing")
    print(lang, result["translatedUrl"])

Node.js (18 or later, as an ES module, with the built-in fetch and FormData):

import { readFile } from "node:fs/promises";

const form = new FormData();
const image = new Blob([await readFile("product-front.jpg")], { type: "image/jpeg" });
form.append("file", image, "product-front.jpg");
form.append("target_lang", "ja");

const response = await fetch("https://translatemyimage.com/api/translate", {
  method: "POST",
  headers: { "X-API-Key": process.env.TMI_API_KEY },
  body: form,
});
const payload = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${payload.error}`);
console.log(payload.translation.translatedUrl);

One target_lang per request: to translate an image into five languages, send five requests.

Handle every status code

StatusMeaning (from the reference)What your code should do
200Translation completed; one credit consumedDownload and store the translated image
400Invalid input, unsupported format or missing fileDo not retry. Validate type, size (10 MB), resolution (25 MP) and language code before sending
401Missing, invalid or revoked API keyDo not retry. Check the key and how it is loaded
403The account that owns the key is not on the Pro plan or above, which API access requiresDo not retry. Check the plan of the account that created the key
429The image service is rate limitedRetry later with exponential backoff
500Processing failedCheck code first: insufficient_credits means the account needs credits, so a retry will not help. Otherwise retry once or twice, then log the file for manual handling

The reference documents these six statuses. The endpoint can also return others, for example 422 when no image could be generated (code: generation_failed) or 503 when the image service is unavailable (service_unavailable), so branch on code rather than on the status alone.

Build it yourself or call an image-to-image API?

Instead of an image-to-image API, you can assemble a pipeline: an OCR service to find the text (Google Cloud Vision, for example, returns the extracted text with the bounding box of each word, per its OCR documentation), a text translation API, then code that erases the original text and typesets the translation in the same boxes with a matching font.

OCR + text translation + your own renderingTranslateMyImage API
What you getText strings with coordinates, then whatever you renderA URL to a finished translated image
ControlFull: fonts, enforced glossaries, editable layersMode (business_type) and custom_prompt
Engineering effortSeveral services plus rendering code to build and maintainOne HTTP request per image and language
Target languagesWhatever your translation service supports9
Translated text as dataYesNo, the API returns an image
Pixels outside the textUntouchedRegenerated with the image: digits, small text and logos can change

Build it yourself when you need the translated text as data (alt text, search), strict terminology enforcement, editable layers, more languages, or pixels outside the text that must stay identical. Call the API when you want finished visuals in a few languages and can review them before use.

A production workflow

  1. Validate locally before sending: file type, 10 MB, 25 megapixels, a supported target_lang.
  2. Queue one job per image and language, and back off on 429.
  3. Copy the result to your own storage or DAM with the source ID, target language, translation.id and createdAt. Neither the reference nor the privacy policy promises how long translatedUrl stays available, so do not rely on it as permanent hosting. It is an unsigned storage link: treat it as public.
  4. Mark every output "to review". A person who reads the target language checks prices, specifications and legal text first, then headlines. The batch translation page has a review-by-risk table you can reuse.
  5. Publish only reviewed images, for example to your Amazon listing images.

Before writing code, run a few representative images through the web uploader with the mode you plan to use. For occasional jobs without code, batch translation in the dashboard is simpler: up to 10 images and 50 translated outputs per batch.

Plans and credits

API access is included from the Pro plan up: Pro comes with 100 credits a month and Premium with 300 (pricing). Each completed translation consumes one credit. Pay-as-you-go packs add 1 credit for $2, 30 for $10 or 100 for $20; they do not unlock API access on their own. Every plan with API access also includes Ultra quality and custom_prompt.

Read the API reference

Endpoint, headers, parameters, status and error codes, an example response and calls in cURL, Python and Node.js.

Frequently asked questions

Is there an API that translates the text inside an image?

Yes. The TranslateMyImage API takes an image and a target language and returns a URL to a new image with the text translated, generated to keep the original layout. With a text translation API, you would first extract the text from the image with OCR and then draw the translation back yourself.

Does the API return the translated text?

No. The response contains the translation's ID, the original and translated image URLs, the languages, a status, a timestamp and metadata. If you need the translated text itself, for alt text or search, run an OCR service on the translated image.

Can I translate one image into several languages in one request?

No. Each request has one target_lang. To get five languages, send five requests with the same file; each completed translation uses one credit.

How much does the image translation API cost?

Each completed translation consumes one credit. API access is included from the Pro plan up: Pro costs $9.90 a month with 100 credits, Premium $19.90 a month with 300 credits. Pay-as-you-go packs add credits (1 for $2, 30 for $10 or 100 for $20) but do not unlock API access on their own.

Is there a Python or JavaScript SDK?

The reference documents plain HTTP calls, with examples in cURL, Python (requests) and Node.js (axios). Any HTTP client that can send multipart/form-data with a custom header works.