BlogFindings

inLanguage schema: 429 of 615 home pages carrying parseable JSON-LD named no language in it

Lantad asked all 1,419 hostnames in this repository's committed corpus for robots.txt on 26 September 2026, then read the home page of every host that allowed it with no JavaScript executed. 1,077 answered HTTP 200 with HTML. 615 of them carried at least one JSON-LD block that parsed, and 186 of those 615 put an inLanguage value anywhere in it. The html lang attribute was on 1,016 of the 1,077, and Google's own documentation says it reads none of these tags.

22 min read Lantad

This run counted which of those declarations real home pages actually ship. Lantad requested /robots.txt from all 1,419 hostnames in this repository's two committed corpus seed files on 26 September 2026, evaluated the site root against its own crawler token before asking for anything else, then requested the home page of every host that allowed it and parsed the raw bytes with no JavaScript executed. 1,077 answered HTTP 200 with an HTML content type. The interesting number turned out not to be how often the declarations contradict each other, which is rare, but how often the one inside the structured data is simply absent.

In short

  • Lantad read 1,077 home pages on 26 September 2026 and found 615 carrying at least one JSON-LD block that parsed as JSON. 186 of those 615 carried an inLanguage value somewhere in that markup and 429 carried none, so most pages that ship structured data at all say nothing in it about what language they are written in.
  • The inLanguage schema property was the least used of the five language declarations counted on those 1,077 pages: 1,016 carried a non-empty html lang attribute, 274 carried an og:locale, 186 carried inLanguage, 179 sent a Content-Language response header and 23 carried the meta content-language pragma that the HTML Standard marks non-conforming.
  • Google's documentation on managing multi-regional and multilingual sites, carrying Last updated 2025-12-10 UTC, states that Google uses only the visible content of a page to determine its language and that it does not use any code-level language information such as lang attributes, or the URL.
  • Agreement was the rule and not the exception: 498 of the 1,077 pages carried two or more of these declarations and had them all agree on the primary language subtag, while 7 carried declarations that disagreed. Three of the 7 sent a Content-Language header of und, the subtag RFC 5646 reserves for Undetermined, while their own html lang named a language: insee.fr said fr, commerzbank.de said de-DE and wellsfargo.com said en.
  • Which pages carried inLanguage followed the publishing platform rather than the size of the site. 35 of the 36 WordPress home pages with parseable JSON-LD carried an inLanguage value on 26 September 2026, against 2 of 53 Wix and Squarespace pages and 2 of the 40 pages in the ecommerce stratum.
StageCountWhat happened
Hostnames asked1,419The committed corpus, an editorial frame rather than a random draw
robots.txt never returned a status29No home page was requested for these
Disallowed LantadBot at the root6512 by an explicit rule, 53 because robots.txt answered 5xx, which this parser treats as disallow
Home pages requested1,325Every host whose robots.txt allowed the root
Did not answer 200 with HTML248216 answered 403, 8 answered 202, 6 answered 429, 5 answered 503, 4 answered 404, 2 answered 406, 1 each answered 401, 405, 451, 498 and 500, 1 returned a non-HTML body on a 200 and 1 request aborted
Home pages read1,077The denominator for every declaration count below
Carried a non-empty html lang attribute1,01660 carried no lang attribute and 1 carried the empty string
Carried at least one parseable JSON-LD block615The denominator for every inLanguage figure
Carried an inLanguage value186429 of the 615 carried none
One GET of https://<host>/robots.txt, then one GET of https://<host>/, each sent as LantadBot/1.0 with redirects followed, a twenty second timeout on each request, no JavaScript executed and from one network location. robots.txt was parsed with parseRobotsTxt and evaluated for LantadBot at the site root with evaluateRobots, both imported directly from core/src/robots.ts, before any home page was requested. Measured by Lantad on 26 September 2026 across the 1,419 hostnames in worker/seeds/corpus-seeds-platform.json and worker/seeds/corpus-seeds-industry.json.

What is the inLanguage schema property for, and what does it require?

The vocabulary definition is one sentence long. The schema.org entry for inLanguage defines it as "The language of the content or performance or used in an action" and then adds an instruction rather than a rule: "Please use one of the language codes from the IETF BCP 47 standard." Its expected types are Language or Text, and it is available on seven types, among them CreativeWork, which is the ancestor of almost every type a home page declares.

Two things follow from that wording and both matter for what the measurement found. The property is optional, so a page that omits it is not malformed, exactly as a page carrying no @id on any node is not malformed even though it has given up saying that two statements are about one thing. And the expected type includes Text, so the vocabulary itself does not reject the string "English". The BCP 47 instruction is advice in prose, which a validator has no obligation to enforce and, as the values below show, some publishers have not read.

The tag syntax the instruction points at is specified separately. RFC 5646, the Standards Track document behind BCP 47, defines the subtag structure and also defines the escape hatch that three sites in this sample used without apparently meaning to: it records that "The special value 'und' (Undetermined) has a 'Scope' of 'special'". A tag exists whose entire meaning is that the language is not known, and it is well formed, so nothing in a syntax check will flag it.

This is the same shape as the defect class counted when this corpus found 117 of 612 home pages with JSON-LD carrying a defect: markup that passes a checker while failing to say anything a consumer can use. What follows is a count of how often the property appears at all, what its values look like when it does, and what the pages that skip it fall back on.

schema.org, the vocabulary

  • inLanguage: The language of the
  • content or performance or used in
  • an action.
  • Please use one of the language codes
  • from the IETF BCP 47 standard.
  • Expected types: Language or Text.
  • Says: what the property means.

RFC 5646, the tag syntax

  • The special value 'und'
  • (Undetermined) has a 'Scope' of
  • 'special'.
  • So a well formed tag can mean
  • the language is not known, and
  • no syntax check will object.
  • Says: what a code is allowed to be.
The two published documents behind an inLanguage value, quoted exactly as read at source on 26 September 2026. The schema.org page carries no date; RFC 5646 is a Standards Track document published in September 2009.

How many home pages carried inLanguage at all

Of the 1,077 home pages read, 622 carried at least one script element with type application/ld+json and 615 carried at least one such block that parsed as JSON. That leaves the same denominator this corpus produced when it counted what sites do with the @id keyword, and it is the population every figure in this section is drawn from.

186 of those 615 pages carried an inLanguage value somewhere in their markup. 429 did not. Put next to the other four declarations the ordering is stark. The html lang attribute was present and non-empty on 1,016 of the 1,077 pages, which is 94 percent of everything read. og:locale, a property built for social link previews rather than for crawlers, was on 274, which is the same family of tags an earlier run counted when it found 38 home pages that named themselves nowhere a machine could read. inLanguage was on 186. A Content-Language response header arrived on 179. The meta content-language pragma was on 23.

So the declaration that lives inside the structured data, on the pages that went to the trouble of publishing structured data, is roughly a fifth as common as the attribute sitting in the opening tag of the same document. That is not a case of publishers choosing one mechanism over another, because these are not alternatives: the lang attribute describes the document to a browser and the inLanguage property describes a typed thing to a consumer of the graph. A page can carry both and 184 of the 186 did.

Counting declarations per page makes the distribution clearer. 55 of the 1,077 pages carried none of those five declarations. 517 carried exactly one, which on all but a handful was the lang attribute alone. 360 carried two, 141 carried three, 4 carried four, and no page in the sample carried all five. The 55 that carried none are not all empty shells waiting on a script bundle, which is the usual explanation when a page appears to say nothing: 30 of them carried 100 words or more of readable prose in the delivered bytes, and the two largest, daytona.io and medscape.com, each carried more than 5,000 words. Those two are pages with plenty for a crawler to read and no statement anywhere about what language it is in, which is a different situation from a page that returns no words at all.

  • html lang attribute, non-empty 1016 pages Of 1,077 pages read
  • og:locale meta property 274 pages Built for link previews, not crawlers
  • inLanguage in JSON-LD 186 pages 186 of the 615 pages with parseable JSON-LD
  • Content-Language response header 179 pages 22 distinct values, 3 of them und
  • xml:lang on the html element 26 pages Alongside lang on all 26
  • meta http-equiv content-language 23 pages Non-conforming per the HTML Standard
  • None of the five counted declarations 55 30 of them carried 100 words or more of prose
Pages carrying each declaration, of the 1,077 home pages that answered HTTP 200 with HTML on 26 September 2026. inLanguage is counted against the same 1,077 for comparability; against the 615 pages carrying parseable JSON-LD it is 186, or 30 percent. Measured by Lantad from one network location with no JavaScript executed.

Which language declaration does a parser actually use?

For the HTML document the answer is written down, and it does not include the structured data at all. The WHATWG HTML Standard, in its section on the lang and xml:lang attributes at html.spec.whatwg.org/multipage/dom.html, defines the lang attribute as specifying "the primary language for the element's contents and for any of the element's attributes that contain text", and requires that "Its value must be a valid BCP 47 language tag, or the empty string." It then sets out an ordered fallback: the xml:lang attribute if present, otherwise the lang attribute, otherwise the language of the parent element, otherwise a pragma-set default language, otherwise "language information from a higher-level protocol (such as HTTP), if any, must be used as the final fallback language instead."

Only at the end of that chain does the specification give up: "In the absence of any such language information, and in cases where the higher-level protocol reports multiple languages, the language of the node is unknown, and the corresponding language tag is the empty string." The inLanguage property appears nowhere in the sequence, which is correct rather than an omission. JSON-LD describes things; the lang attribute describes the document. A consumer reading the graph and a consumer rendering the page are asking different questions and the specifications answer them separately.

Two consequences of that chain showed up in the measurement. The pragma-set default language is set by the meta content-language element, and the HTML Standard's own table of http-equiv keywords, at html.spec.whatwg.org/multipage/semantics.html, lists that keyword as conforming: No, with the note "This feature is non-conforming. Authors are encouraged to use the lang attribute instead." 23 pages still ship it. The same section also specifies that if the content attribute "contains a U+002C COMMA character (,), then return", so a comma-separated pragma sets nothing at all. None of the 23 used a comma, but 2 of them, forbes.com and ing.com, sent en_US with an underscore, which is not a well formed BCP 47 tag, and the lang specification says such a value "must be treated as an unknown language having the given language tag, distinct from all other languages."

The header at the end of the chain means something narrower than most of its users appear to think. RFC 9110 section 8.5 defines Content-Language as describing "the natural language(s) of the intended audience for the representation" and warns in the next sentence that "this might not be equivalent to all the languages used within the representation." It is a statement about who the content is for, not about what it is written in. A page in English aimed at a Danish-literate audience is the specification's own example of the difference, and the two declarations disagreeing on such a page would be correct rather than a defect.

The ordered fallback for the language of a node, as specified in the HTML Standard section on the lang and xml:lang attributes, read at source on 26 September 2026. Each step is consulted only when the one above it is absent. The inLanguage property in JSON-LD appears nowhere in this chain.

What the 186 inLanguage values actually said

The 186 pages carrying the property held 38 distinct values between them, and the distribution is narrow: en-US on 101 pages, a bare en on 45, en-GB on 5, then en-AU, en-us and es on 3 pages each and a long tail of vi, fr, fi, nl, de-DE, it-IT, nb-NO, en-CA, en-ZA and the rest on one or two pages. Three pages wrote en-us in lower case, which is well formed, since BCP 47 subtag case is a convention rather than a requirement.

184 of the 186 held only values that Node's Intl.getCanonicalLocales accepts as well formed BCP 47 tags. That test is a structural one and worth stating precisely, because it is weaker than it sounds: it checks the shape of the subtags, not whether a language with that code exists. Two pages failed it. unacademy.com put the single string "Hindi, English" in one inLanguage value, which a comma makes unparseable as one tag, and kaiserpermanente.org sent an empty string, which the vocabulary gives no meaning to at all.

The structural test also passes things the schema.org instruction plainly rules out, and that is where the more interesting values sit. A BCP 47 primary language subtag for an ordinary language is two or three letters, so a value whose primary subtag runs to four letters or more is a language name rather than a code. Two pages shipped one. meininger-hotels.com listed eight of them, "English", "German", "French", "Spanish", "Dutch", "Italian", "Danish" and "Polish", and nbcnews.com carried both en-US and the bare word "English" in different nodes of the same document. A consumer honouring the instruction to read BCP 47 gets nothing usable from either, and a syntax validator reports no error, because "English" is seven letters and BCP 47 reserves five-to-eight-letter primary subtags for registered use.

7 pages carried more than one distinct inLanguage value, and they do not all mean the same thing. On three of them the multiple values look like the property working as intended: germany.travel declares en, es, fr and de, emiratesnbd.com declares en and ar, and both are genuinely multilingual sites whose home page offers those languages. On the rest the values are in tension. bindwell.ai declares en, zh and hi. etobicokerehab.com declares en-CA on one node and en-US on another. usz.ch, a Swiss university hospital, declares en-US on one node and de-DE on another while its lang attribute and og:locale both say German. That last page is not wrong so much as unresolved, and saying which node the language belongs to is exactly what an @id reference is for, which is the mechanism most of these pages do not use to join two statements about one thing.

Value shapePagesExamplesWhat a BCP 47 consumer gets
Well formed tag184en-US on 101 pages, en on 45, en-GB on 5, en-AU and en-us on 3 eachA usable language tag
Language name, not a code2meininger-hotels.com sent English, German, French, Spanish, Dutch, Italian, Danish and Polish; nbcnews.com sent en-US and EnglishStructurally valid, semantically nothing
Comma-joined names1unacademy.com sent the one string Hindi, EnglishRejected as a tag
Empty string1kaiserpermanente.orgRejected as a tag
More than one distinct value on a page7germany.travel sent en, es, fr and de; usz.ch sent en-US and de-DE while its lang said deCorrect on a multilingual page, ambiguous without an @id otherwise
Every inLanguage value on the 186 home pages that carried one, grouped by what a consumer reading BCP 47 can do with it. Well formed means accepted by Node's Intl.getCanonicalLocales, a structural check on subtag shape rather than a check that the language exists. Measured by Lantad on 26 September 2026 and re-verified on each named host by a second independent request the same day.

Where a page's own language declarations contradicted each other

The result worth reporting here is the one that argues against the premise. Contradiction is rare. 498 of the 1,077 pages carried two or more declarations that all agreed on the primary language subtag. 7 carried declarations that disagreed. On a corpus assembled to span platforms and industries, the five declarations very largely say the same thing, and a post that had gone looking for widespread inconsistency would have had to invent it.

Three of the 7 are the same defect, and it is a specific one. insee.fr, commerzbank.de and wellsfargo.com each send a Content-Language response header of und while their own html lang attribute names a real language: fr, de-DE and en respectively. As RFC 5646 records, und is the reserved subtag for Undetermined, so these three servers are attaching a header to every response that says the intended audience's language is not known, on pages whose markup states it plainly one line into the document. All three reproduced on a second independent request the same day. This is almost certainly a default left in a platform configuration rather than a decision, which is what makes it worth naming: nothing in a validator or a browser will ever surface it.

The remaining four are content mismatches rather than header defaults. misa.vn carries lang="en" with og:locale vi_VN and inLanguage vi, on a home page of 5,322 words whose delivered text holds 3,131 characters carrying Vietnamese-specific diacritics out of 25,567, so the lone declaration saying English is the one the HTML Standard's fallback chain reaches first on that page. meininger-hotels.com carries lang="en" and a Content-Language of en-US alongside og:locale de_DE and the eight language names above. usz.ch and unacademy.com are the two already described.

What none of this measures is whether any declaration matches the prose. Comparing a declared tag against the actual language of the text would need a language identification model, this run did not use one, and no figure above should be read as a claim that a page is or is not in the language it declares. The one exception is narrower than a language check and is stated as exactly what it is: on misa.vn, a count of characters carrying diacritics that appear in Vietnamese and not in English put 3,131 of them in the delivered text, which is a character census rather than an identification of the language. The count of 7 is a count of declarations disagreeing with each other, which is a strictly narrower and strictly checkable thing, and it is the same reason an earlier run reported what changed on a header rather than what the text said.

Hosthtml langog:localeContent-LanguageinLanguage
insee.frfrnoneundnone
commerzbank.dede-DEnoneundnone
wellsfargo.comennoneundnone
misa.vnenvi_VNnonevi
usz.chdede_DEnoneen-US and de-DE
meininger-hotels.comende_DEen-USEnglish and seven more names
unacademy.comennonenoneHindi, English
The 7 home pages of 1,077 whose own language declarations disagreed on the primary subtag, measured by Lantad on 26 September 2026 and re-verified on every host by a second independent request the same day. A dash means the page sent nothing in that slot.

Google documents that it uses none of these tags to decide language

The inconvenient part of this measurement is that the largest consumer of the markup says the markup is not what it reads. Google's documentation on managing multi-regional and multilingual sites, carrying Last updated 2025-12-10 UTC, states that Google uses only the visible content of a page to determine its language, and that "We don't use any code-level language information such as lang attributes, or the URL."

Read that against the counts above and the ordering inverts. The declaration 1,016 pages ship is explicitly excluded. The pragma 23 pages ship is non-conforming in the specification that defines it. The header 179 pages ship describes an intended audience rather than a language, by its own definition. And the inLanguage property, the one only 186 of 615 structured-data pages bother with, has no documented consumer at all: no crawler vendor publishes what it does with the value, which is the same silence this blog found when it looked for documented behaviour on Accept-Language in Googlebot's requests.

That does not make the tags pointless, and the honest version of the finding needs both halves. Browsers, screen readers, hyphenation, font selection, spell checking and CSS :lang selectors all consume the lang attribute, and the HTML Standard's note that "User agents may use the element's language to determine proper processing or rendering (e.g. in the selection of appropriate fonts or pronunciations, for dictionary selection, or for the user interfaces of form controls such as date pickers)" is a real list of real consumers. The attribute earns its place on accessibility grounds alone. What it does not do, on the documentation as published, is tell Google what language your page is in.

For an AI crawler the position is weaker still, because nothing is documented in either direction. This scan sent LantadBot, so nothing here is a claim about what GPTBot, ClaudeBot or PerplexityBot does with a language tag. What can be said is what those crawlers are given: a page whose lang attribute is absent on 60 of 1,077, whose structured data declares a language on 186 of 615, and whose visible prose is therefore the only signal present on every single page in the sample. If a model is inferring language from the text, it is inferring it from the one input that never went missing. The practical reading for anyone auditing their own markup with the robots.txt and crawler tools here is to fix the declarations for the consumers that documented their use of them, and not to expect a language tag to move a citation in an AI Overview.

  • html lang attribute Browsers and assistive tech The HTML Standard names font selection, pronunciation, dictionaries and form controls. Google's page says it is not used for language determination.
  • Content-Language header Intended audience only RFC 9110 section 8.5 defines it as the language of the intended audience, which it says might not match the languages in the content.
  • meta content-language Non-conforming The HTML Standard lists the keyword as conforming: No and tells authors to use the lang attribute instead.
  • inLanguage in JSON-LD No documented consumer schema.org defines the property and asks for BCP 47 codes. No crawler vendor documents what it does with the value.
  • Visible prose What Google documents using Google's multi-regional documentation, Last updated 2025-12-10 UTC, states it uses only the visible content of the page.
What each language declaration's documented consumers are, from the specifications and vendor documentation read at source on 26 September 2026. Where a row says nothing is documented, that is the absence of a published statement rather than evidence that the value is ignored.

The publishing platform decided this, not the size of the site

The split by corpus stratum is the cleanest pattern in the run and it repeats a shape this corpus has produced before. Of the WordPress home pages carrying parseable JSON-LD, 35 of 36 carried an inLanguage value. Of the Wix and Squarespace pages, 2 of 53 did, and of the pages in the ecommerce stratum, 2 of 40. Between those poles sit media-local at 16 of 28, saas-marketing at 13 of 24, news at 20 of 51, saas at 32 of 89, government at 6 of 28, healthcare at 9 of 45 and finance at 10 of 53.

A site owner did not choose that, and the most likely explanation is a default rather than a decision: on almost all of these sites the JSON-LD is written by the platform or by an SEO plugin rather than by hand, so whether the graph carries an inLanguage value is settled by whichever template emits it. This run did not identify the generator behind each page, so that is an inference from the distribution and not a measurement of which plugin wrote what. What the distribution does show is that the sites in the Wix and Squarespace stratum get whatever their host emits, which is the same reason not one of 69 Wix robots.txt files named an AI crawler. The same mechanism produced the @id finding in the earlier run on what sites do with node identifiers, where all the WordPress pages carried an @id and almost none of the Wix and Squarespace pages did, and the same mechanism is why WordPress robots.txt files name AI crawlers so rarely while their schema output is comparatively complete. A platform is good at whatever its default template is good at.

The 60 pages with no lang attribute at all distribute the same way, and the concentration is worth a line because it is not where a reader would guess. 11 of the 60 were in the healthcare stratum and 7 in finance, against 1 in news and 2 in the saas stratum. Those are two of the most regulated categories in the corpus, and the absence of the single cheapest accessibility declaration on their home pages is a finding about template maintenance rather than about compliance, since no regulation cited on this site requires the attribute.

One more figure belongs here because it constrains everything above. 293 of the 1,016 lang attributes carried a region or script subtag such as en-US or pt-BR, and 723 carried a bare primary subtag such as en. Not one of the 1,016 failed the structural BCP 47 check. Whatever is wrong with language declaration on the modern web, malformed lang attributes are not it, which is a better outcome than this corpus has recorded for schema syntax or for robots.txt files, where a 5xx and a 404 mean opposite things. The gap is in the declarations further down: the property inside the structured data, absent on 429 of 615, and the header that says und on three major institutions' home pages.

  • wordpress-smb 97% (35 of 36)
  • media-local 57% (16 of 28)
  • saas-marketing 54% (13 of 24)
  • news 39% (20 of 51)
  • saas 36% (32 of 89)
  • education 29% (9 of 31)
  • travel 28% (10 of 36)
  • government 21% (6 of 28)
  • healthcare 20% (9 of 45)
  • finance 19% (10 of 53)
  • shopify-dtc 9% (2 of 22)
  • ecommerce 5% (2 of 40)
  • wix-squarespace 4% (2 of 53)
Share of home pages carrying parseable JSON-LD that also carried an inLanguage value, by corpus stratum, measured by Lantad on 26 September 2026. The denominator is pages with parseable JSON-LD in that stratum, printed after each bar. Strata are the sampling frame in the two committed seed files, not a random draw of the web.

Written by

Lantad

Published .

Ask a web page what language it is written in and you can get six answers from six different places, none of which is required to agree with the others. Five are declarations a machine can read without understanding a word of the text: the lang attribute on the html element, the og:locale meta property, a meta pragma that predates both, the Content-Language response header, and the inLanguage property inside structured data. The sixth answer is the prose itself, which is the only one that cannot be wrong and the only one nobody has to write down.

Common questions

Does the inLanguage schema property affect AI search visibility?

No published evidence says it does, and this post does not claim it. schema.org defines the property and asks for a BCP 47 code, but no crawler vendor documents what it does with the value, and Lantad measured no citation or retrieval outcome in this run. What was measured is adoption: 186 of the 615 home pages carrying parseable JSON-LD on 26 September 2026 carried an inLanguage value and 429 carried none. Set it because it makes your graph self-describing, not because anything published promises a ranking or citation effect.

Does Google use the html lang attribute to determine a page's language?

No. Google's documentation on managing multi-regional and multilingual sites, carrying Last updated 2025-12-10 UTC, states that Google uses only the visible content of a page to determine its language and that it does not use any code-level language information such as lang attributes, or the URL. The attribute still matters for browsers and assistive technology, which the HTML Standard names as consumers for font selection, pronunciation, dictionary selection and form controls, so it is worth setting correctly on accessibility grounds.

What does a Content-Language header of und mean?

It means the language is Undetermined. RFC 5646 reserves und as a special-scope subtag for exactly that, so it is a well formed tag and no validator will flag it. Three home pages in this sample sent it while their own html lang attribute named a real language: insee.fr said fr, commerzbank.de said de-DE and wellsfargo.com said en. In each case it is far more likely to be a platform default nobody changed than a deliberate statement, which is why it survives: nothing in a browser or a checker surfaces it.

Should I use meta http-equiv content-language?

No. The HTML Standard lists the content-language keyword in its http-equiv table as conforming: No, with the note that the feature is non-conforming and authors are encouraged to use the lang attribute instead. It also specifies that a content value containing a comma is discarded entirely, so a multi-language pragma sets nothing. 23 of the 1,077 pages read on 26 September 2026 still carried it, and 2 of those, forbes.com and ing.com, sent en_US with an underscore, which is not a well formed BCP 47 tag.

See what AI can read on your site

Run a free scan and get a graded report of exactly what AI crawlers can and cannot read, with ranked fixes.