Back to blog
Split-screen flat illustration on a white background. Left side shows a simple document icon labeled “.txt” in muted blue-grey, producing a single output document tagged “EN.” Right side shows a JSON file with visible nested keys, connected to three separate document outputs labeled “EN,” “FR,” and “ES.” The right side uses teal and amber accents. A thin vertical line divides the two halves. Clean geometric style, minimal detail, no people or branding.

PolyLingo vs DeepL API: which preserves JSON and Markdown better?

By Robert M

PolyLingo vs DeepL API: which preserves JSON and Markdown better?

DeepL makes genuinely excellent translation software. Its neural translation engine is widely regarded as one of the best available, and for plain prose it is hard to beat. If you are translating sentences, paragraphs, or documents written as continuous text, DeepL is a strong choice.

The question this post is answering is a narrower one: how does the DeepL API perform when your content has structure? When you need to translate a JSON locale file without touching the keys, or a Markdown blog post without breaking the syntax, or an HTML page without mangling the attributes? And how does it compare to PolyLingo for that specific use case?


How the DeepL API is built

The DeepL text translation API accepts plain text. That is its native input format. Each request accepts up to 50 text strings and they are translated independently, without shared context between them. Only one target language can be specified per request. If you need five languages, you make five requests.

DeepL does support document translation for formats like PDF, Word, PowerPoint, and HTML, but that goes through a separate document endpoint with a different flow: upload the file, poll for completion, download the result. It is designed for office documents, not for programmatic content pipelines.

For HTML specifically, there is a tag_handling parameter you can set to html, which tells DeepL to treat the input as HTML and attempt to preserve tags. This works reasonably well for simple markup, but it is an optional flag you have to know to set, and it does not extend to JSON or Markdown.

For JSON, there is no native support. DeepL's text endpoint does not know what a JSON key is. If you send it a serialised JSON object, it will translate the content as a string and there is no guarantee that keys, structure, or non-string values will survive intact. The babeldown R library, which wraps DeepL for Markdown content, has documented cases where DeepL mixes up punctuation inside Markdown links and formatting, which is a known limitation of passing structured text through a plain-text translation engine.

This is not a criticism of DeepL. It is a description of what the API was designed to do. DeepL's core use case is high-quality translation of human-readable prose. That is what it optimises for and it is excellent at it.


Where the gap shows up in practice

The difference becomes visible the moment your content is not plain prose.

Consider a standard Next.js locale file:

{
  "nav": {
    "home": "Home",
    "about": "About us",
    "contact": "Get in touch"
  },
  "hero": {
    "title": "Welcome to our platform",
    "subtitle": "Everything you need in one place"
  }
}

To translate this with the DeepL API into five languages you would need to:

  1. Extract each string value individually
  2. Make a separate API request per language (five languages, five requests)
  3. Reconstruct the JSON structure with the translated values in the right places
  4. Handle any cases where the translation altered punctuation or introduced characters that break JSON validity That is a non-trivial amount of glue code. It is also fragile. Any deviation in the translation output from what your parser expects will cause a silent failure or a runtime error in your application.

With PolyLingo you send the object as-is with format: "json" and receive back a translated version of the complete structure for every target language in one response. Keys are untouched. Nesting is preserved. Non-string values are left alone. The output drops straight into your project.

curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "{\"nav\":{\"home\":\"Home\",\"about\":\"About us\"}}",
    "format": "json",
    "targets": ["fr", "de", "es", "ja", "nl"]
  }'

One request. Five languages. Structure intact.


Markdown content

The same pattern applies to Markdown. DeepL's text endpoint has no concept of Markdown syntax. Send it a blog post and it will process the whole thing as a string. Headings may survive. Code blocks almost certainly will not, as the content inside them is likely to be treated as translatable text. Link syntax may be mangled, particularly around punctuation at the boundaries of link text.

PolyLingo's markdown format flag instructs the model to treat Markdown syntax as structural rather than translatable. Headings stay headings. Fenced code blocks are left verbatim. Link URLs are not altered. Only the prose content changes.

For a documentation site or a blog with technical content, the difference is significant. A corrupted code block in a tutorial is not a minor presentation issue, it is a broken tutorial.


The one request vs one-per-language difference

This is worth dwelling on because the cost implications are real.

DeepL's API accepts only one target language per request. To translate a piece of content into ten languages you make ten API calls. For a large site or a CMS with frequent publishing, that is ten times the request overhead, ten times the latency to manage, and ten times the points of failure.

PolyLingo accepts an array of target language codes and returns all translations in a single response. Thirty-six languages is one request, not thirty-six.

For small projects the difference is manageable. For anything at scale it changes the architecture of how you build your translation pipeline.


Pricing model

DeepL charges by character. The API Free plan allows up to 500,000 characters per month, and paid plans bill on character consumption. Because you make one request per language, the character count for a piece of content is multiplied by the number of target languages you are sending it to across separate requests.

PolyLingo charges by token and counts across the combined input and output for all languages in a single request. The billing is transparent and predictable: the free tier includes 50,000 tokens per month, with paid plans starting at $9 per month for 600,000 tokens.

The two models are not directly comparable on a cost-per-word basis because they use different units, but the single-request-all-languages architecture of PolyLingo means you are not multiplying your request count linearly with the number of target languages.


Where each one fits

DeepL API is the right choice when:

  • Your content is plain prose with no structural requirements

  • Translation quality for human-readable text is the primary concern

  • You are translating into a small number of languages and request volume is low

  • You are already invested in the DeepL ecosystem and using their glossary or formality features

  • You need support for a language outside PolyLingo's current 36 (DeepL supports over 100 languages) PolyLingo is the right choice when:

  • Your content is JSON, Markdown, or HTML and structure must be preserved

  • You need to translate into multiple languages in a single API call

  • You are building a CMS integration or i18n pipeline where request efficiency matters

  • You want a consistent interface across all content formats without format-specific workarounds

  • You want token-based billing with a predictable monthly grant


Side-by-side summary

PolyLingoDeepL API
Native JSON supportYesNo
Native Markdown supportYesNo
HTML supportYesYes (tag_handling flag)
All languages in one requestYesNo, one language per request
Auto-detects content formatYesNo
Languages supported36100+
Free tier50,000 tokens/month500,000 characters/month
Billing unitTokenCharacter
No-code web translatorYesYes (web app)

DeepL has a larger language catalogue and a longer track record for prose translation quality. PolyLingo is purpose-built for structured content workflows where format integrity is non-negotiable.

They are solving adjacent problems. The right choice depends on what your content actually looks like.


Try PolyLingo

The free tier includes 50,000 tokens per month. No credit card required. Full API documentation is at usepolylingo.com/docs.

curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "# Hello\n\nThis is **structured** content.",
    "format": "markdown",
    "targets": ["fr", "de", "es"]
  }'

Get your API key