Back to HTTP Headers

Content-Language content both

Describes the natural language(s) of the intended audience for the message body.

What it does

Content-Language describes the natural language(s) of the intended audience for the message body. It's not about the language the content is written in — it's about the audience the content is for. A document written in English but intended for French speakers learning the language could technically have Content-Language: fr.

In practice, the distinction rarely matters. Most implementations treat it as "the language this content is in."

Syntax

Content-Language: <language-tag>
Content-Language: <language-tag>, <language-tag>

Language tags follow BCP 47 (the same format as the HTML lang attribute). Common examples:

Content-Language: en
Content-Language: en-US
Content-Language: fr-CA
Content-Language: zh-Hans
Content-Language: en, fr

Language tag format

BCP 47 language tags are structured as subtags separated by hyphens:

Tag Meaning
en English (any variant)
en-US English as used in the United States
en-GB English as used in Great Britain
fr French
fr-CA French as used in Canada
zh-Hans Chinese written in Simplified script
zh-Hant Chinese written in Traditional script
pt-BR Portuguese as used in Brazil
ar Arabic

How it interacts with other headers

Content-Language and Accept-Language are a negotiation pair. The client sends Accept-Language with a prioritized list of languages it prefers; the server responds with the best match and declares the language in Content-Language.

Vary: Accept-Language should accompany multilingual responses so caches know to store separate cached versions per language. Without it, a cache might serve a French response to an English-speaking user.

Content-Language in HTTP is distinct from the HTML lang attribute. For HTML pages, the lang attribute on the <html> element is the authoritative language declaration for the document — screen readers, search engines, and CSS all rely on it. Content-Language in the HTTP header is primarily for caching and content negotiation infrastructure. Use both.

Common mistakes and gotchas

Omitting Vary: Accept-Language on cached multilingual responses. If your server returns different language versions of the same URL based on Accept-Language, and you don't add Vary: Accept-Language, a CDN or browser cache will serve the first cached version to all users regardless of their language preference.

Setting it to the wrong language. Sounds obvious, but if content is generated dynamically (user profiles, database records), make sure the declared language matches the actual content language. A mismatch confuses screen readers and search engine indexing.

Using non-standard language codes. Use BCP 47 codes, not ISO 639 alone (though BCP 47 incorporates ISO 639). en-US not en_US (hyphen not underscore). Some old implementations used underscore variants, but that's incorrect per spec.

Setting Content-Language on JSON API responses. For pure data APIs returning JSON, Content-Language is usually irrelevant — the data structure isn't language-specific even if string values are. Set it on human-readable content: HTML pages, plain text responses, localized error messages.

Real-world examples

HTML page in French:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Language: fr-FR
Vary: Accept-Language

Multilingual document:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Language: en, fr

API returning localized error message:

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
Content-Language: de

{"error": "Das Passwort muss mindestens 8 Zeichen lang sein."}

FAQ

Is Content-Language required?

No, it's optional. Many sites omit it entirely and rely on the HTML lang attribute for browser language detection. For SEO and accessibility, the lang attribute on the HTML element is more important. Content-Language becomes important when you have content negotiation infrastructure (multiple language versions at the same URL) and want caches to handle them correctly.

What's the difference between Content-Language and the HTML lang attribute?

Content-Language is an HTTP header — it lives in the transport layer and is visible to proxies, CDNs, and crawlers before they parse the document. The HTML lang attribute is inside the document itself. For web pages, use both: Content-Language for caching/infrastructure, lang attribute for browsers, screen readers, and search engines. Content-Language takes priority for HTTP-level processing; lang takes priority for rendering.

Can Content-Language list multiple languages?

Yes. If a document contains significant content in multiple languages (e.g., a language learning page with English and Japanese), list all of them: Content-Language: en, ja. However, if one language is dominant and others are incidental (a few loan words, a quoted passage), list only the primary language.

Does Content-Language affect SEO?

Indirectly. Search engines like Google use Content-Language and Accept-Language negotiation as signals for language and regional targeting, but the hreflang link attribute and the HTML lang attribute carry more weight for SEO. Get those right first.

Fun fact

The concept of language negotiation in HTTP predates the modern web — it was part of HTTP/1.0 from 1996. The original vision was that browsers would transparently negotiate language with servers so users would always get content in their preferred language. In practice, most sites implement language switching with URLs (/en/, /fr/) or cookies rather than header negotiation, which is why Content-Language and Accept-Language are less central than the spec designers imagined they'd be.