skip to content

What does a `<script type="application/ld+json">` block in an HTML page contain, and what does the browser do with its contents when it parses the page?

level: juniorimportance: must knowfreq 68%

answer

  1. inert, not executable
  2. type is not a JS MIME type
  3. the HTML spec calls it a data block
  4. @context, @type, @id
  5. raw text — escape the closing tag

basics

~20 s

A script tagged type="application/ld+json" holds JSON-LD data describing the page's entities, usually with schema.org vocabulary. The browser treats it as an inert data block: never executed, never displayed. Machines such as search crawlers read it.

solid answer

~50 s

It holds a JSON object (or array) describing what the page is *about* — an `Article`, a `Product`, an `Organization` — using the schema.org vocabulary. Because the `type` attribute is not a JavaScript MIME type, HTML treats the element as a **data block**: the parser reads the contents as raw text, does not execute them, and `script` is never rendered, so the page looks and behaves exactly the same with or without it. Consumers that care — search crawlers, validators, some scrapers — pull the block out and parse the JSON. The three keywords that make it JSON-LD rather than plain JSON are `@context` (which vocabulary the short property names come from, normally `"https://schema.org"`), `@type` (what kind of thing this node is), and `@id` (a stable identifier for the node). Everything else is ordinary schema.org properties.

code

html · 11 lines
html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "@id": "https://example.com/blog/faster-builds#article",
  "headline": "How we cut build times in half",
  "datePublished": "2026-02-11",
  "author": { "@type": "Person", "name": "Ada Reyes" },
  "publisher": { "@type": "Organization", "name": "Example Labs" }
}
</script>

go deeper

for a junior

Be able to say plainly that the block is data, not code: the browser neither runs nor displays it, and @context plus @type identify the vocabulary and the kind of thing described.

for a middle

Explain why the element is inert — the type is not a JavaScript MIME type, so HTML treats it as a data block of raw text — and name the escaping consequences that follow from raw-text parsing.

for a senior

Show that you treat structured data as a shipped artifact: validated in CI, generated from real page data, and monitored, because a malformed block fails silently and nobody notices from the browser.

for a principal

Own the position that structured data is a contract with external consumers you do not control. Decide which entities are worth asserting at all and who is accountable when the asserted data and the visible page disagree.

## What the browser actually sees HTML says a `<script>` element whose `type` attribute is neither empty nor a JavaScript MIME type is a **data block**. The parser reads its contents as raw text, hands them to no script engine, and moves on. And because `script` is never rendered, nothing appears on screen. `application/ld+json` is exactly such a type, and that is the whole trick behind JSON-LD: you can drop a full machine-readable description of the page into the document without changing one pixel of how it looks or one line of how it behaves. ```html <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "How we cut build times in half", "datePublished": "2026-02-11", "author": { "@type": "Person", "name": "Ada Reyes" } } </script> ``` JSON-LD is "JSON for Linked Data": normal JSON plus a handful of reserved keywords that begin with `@`. ## The keywords **`@context`** maps the plain property names in the object onto a vocabulary. For web structured data it is almost always the string `"https://schema.org"`, which says "when I write `headline` or `author`, I mean schema.org's `headline` and `author`". Without it a consumer sees an untyped bag of strings. **`@type`** names the kind of thing the node is — `Article`, `BlogPosting`, `Product`, `Organization`, `Person`, `BreadcrumbList`, `FAQPage`. The type determines which properties are meaningful; a `Product` has `offers`, an `Article` has `headline`. **`@id`** gives the node a stable identifier, conventionally a URL. It lets one node be defined once and referred to from elsewhere instead of copied, which matters as soon as a page describes more than one entity. A nested object is just another node: `"author": { "@type": "Person", "name": "Ada Reyes" }` describes a Person inline. Child nodes inherit `@context` from the top, so you write it once. ## Where it goes and how many you may have The block is valid in `<head>` or in `<body>`, and search engines document that both are read. A page may carry several separate `application/ld+json` blocks — a common pattern is one per concern (the article, the breadcrumb trail, the organization). A single block may also hold a top-level JSON **array** of nodes. None of these arrangements is more "correct"; pick whatever your templates can generate reliably. ## Two escaping traps that bite in production Because the contents are **raw text**, the parser terminates the element at the first `</script` sequence it sees — even inside a JSON string. If a headline or description legitimately contains that text, the document breaks in a spectacular way: the rest of the JSON spills into the page as visible text. The fix is JSON's own escape for a forward slash, which decodes back to `/`: ```html <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Never write <\/script> in a headline" } </script> ``` The second trap is the mirror image: character references are **not** decoded inside a data block. Writing `&amp;` inside the JSON yields the literal five characters `&amp;`, not `&`. Emit the real character, or the JSON escape `&`. ## What it does and does not buy you It does not style anything, does not run, and cannot be read by CSS. It is not a ranking boost in itself: search engines describe structured data as making a page *eligible* for a rich result — a review star rating, a breadcrumb trail, a product price in the result — not entitled to one. And the data is expected to describe content a user can actually see on the page; markup that asserts a rating or a price that appears nowhere violates search-engine structured-data policy and can earn a manual penalty rather than a richer listing. If the JSON is malformed — a trailing comma, a smart quote from a CMS — consumers skip the whole block silently. The page renders fine, which is exactly why bad structured data can sit unnoticed for months. Run the markup through a structured-data validator as part of the build or a smoke test rather than trusting that "the page looks fine". ## Why interviewers open here The question separates candidates who have shipped SEO-relevant markup from those who have only heard the term. The give-away answers are "the browser runs it" (it does not) and "it changes how the page renders" (it cannot). Knowing that it is inert data, decoupled from the visible DOM, sets up every deeper question about structured data.

  • Does the block have to live in the head, and can one page carry more than one?
    It is valid in either `<head>` or `<body>`, and search engines read both. A page may carry several separate `application/ld+json` blocks, or one block whose top level is a JSON array of nodes. Splitting by concern — article, breadcrumbs, organization — is common because each template fragment can emit its own.
  • What happens if the JSON inside the block is malformed?
    Nothing visible. The browser still ignores the block, so the page renders normally, and consumers that try to parse it discard the whole block rather than salvaging part of it. That silence is the danger: a trailing comma from a template can kill your structured data indefinitely. Validate it in CI or a smoke test.
  • Can CSS or a stylesheet ever reveal the contents of that script block?
    No. `script` is not rendered, and its contents are raw text handed to no renderer. That inertness is the point — the data can be as verbose as the vocabulary needs without any layout or accessibility consequence.

It is a shipping label on a sealed box: the label says what is inside for the machines that route the box, while the box itself is unchanged and the customer never reads the label.

saying these in an interview costs you the question

  • Thinks the browser executes JSON-LD like a script
  • Believes adding JSON-LD changes what users see
  • Omits @context and expects the vocabulary to be inferred
  • Assumes the block must be inside head
  • Writes a literal closing script tag inside a JSON string

context