Migrating from DeepL

The request and response format is intentionally compatible. For most codebases the migration is two lines: the base URL and the key.

The two lines

BeforeAfter
Base URLhttps://api.deepl.com/v2 or https://api-free.deepl.com/v2https://api.vizvuz.com/v1
Keyxxxxxxxx:fxvz_live_xxxxxxxx

The DeepL-Auth-Key header is accepted as well as Authorization: Bearer, which is why the official client libraries usually work without a patch — they only need the base URL changed.

Python

import deepl

translator = deepl.Translator(
    "vz_live_xxxxxxxx",
    server_url="https://api.vizvuz.com/v1",
)
print(translator.translate_text("Hello world", target_lang="DE").text)

Node

import * as deepl from 'deepl-node';

const translator = new deepl.Translator('vz_live_xxxxxxxx', {
  serverUrl: 'https://api.vizvuz.com/v1',
});
const result = await translator.translateText('Hello world', null, 'de');
console.log(result.text);

Plain HTTP

curl -X POST https://api.vizvuz.com/v1/translate \
  -H "DeepL-Auth-Key: vz_live_xxxxxxxx" \
  -d "text=Hello world" -d "target_lang=DE"

What is identical

  • POST /translate with text, target_lang, source_lang, formality,

glossary_id, tag_handling, preserve_formatting, context

  • text as a repeated form field or as a JSON array
  • The response {"translations":[{"detected_source_language":"…","text":"…"}]}
  • GET /languages?type=source|target
  • GET /usage
  • Glossary CRUD, including tab-separated entries and the

/glossary-language-pairs endpoint

  • Language codes, including EN-GB, EN-US, PT-PT and PT-BR

What is different

TopicDifference
ErrorsRFC 9457 application/problem+json with a stable code field, instead of a bare {"message": "…"}
Extra response fieldsWe add request_id and characters to the translate response
Extra headersX-Request-Id, X-Characters-Billed, X-RateLimit-*
Document translationNot available yet — /document endpoints do not exist
split_sentencesNot supported; sentence splitting is handled internally
outline_detectionNot supported
Free tier100,000 characters of credit rather than a separate free host
Key formatOne host for all keys; no :fx suffix and no separate free endpoint
formality valuesAlso accepts prefer_more/prefer_less, which apply formality only where the target supports it instead of erroring — see Formality

If your code branches on DeepL's error message strings, that is the one place that needs real work. Switch it to the code field — see Errors.

A migration that does not surprise anyone

  1. Create a vz_test_ key and point your staging environment at it.
  2. Run your existing translation test suite unchanged. Anything that fails here is

a real incompatibility, not a rounding difference.

  1. Translate a representative sample of your production strings through both

providers and have a native speaker compare them. Do this before you talk about price — quality is the decision, cost is the consequence.

  1. Move production traffic. Keep the old provider configured for a week so a

rollback is a config change, not a deploy.

  1. Delete the old key.

Cost comparison done honestly

Both providers bill per character, including spaces and markup, so a comparison is a straight multiplication — no unit conversion, no seat maths. Take the character count from your last invoice, put it into the calculator on the pricing page and compare the two numbers.

One caveat in our favour that is easy to miss: cache hits are billed here too, so if your workload repeats heavily, measure with your repetition rate rather than assuming either provider's cache changes the bill.

Last updated Sep 1, 2026, 12:00 AM