# Google stopped unrolling double-escaped JSON-LD

> 441 pages audited: Google now applies one pass of HTML unescaping instead of two, and the obvious test for it is the wrong one.

Source: https://cittago.com/blog/json-ld-html-escaping-google-2026/  
Publisher: Cittago — a digital studio in Cluj-Napoca, est. 2011  
Published: 2026-08-26  
Language: en

---

On **21 August 2026** Google said it had changed how it reads structured data: *"To bring our parser up to JSON and other standards, we changed our JSON-LD extraction and are now only applying a single pass of HTML unescaping."* The announcement went out on LinkedIn and, as of 26 August, appears in none of Google's own documentation. The example Google gave to explain it is also the one thing in the announcement that cannot survive being quoted — which is why most write-ups of this change will tell you to check for the wrong thing.

**What changed.** Google's JSON-LD extractor now applies one pass of HTML unescaping instead of two. Single-escaped entities still resolve. Double-escaped ones no longer do: they survive into the value as literal characters, and the field they land in becomes wrong.

**Why most advice about it will be wrong.** The example in the announcement passes through three layers of escaping before it reaches your screen — Google's post, the site reporting it, and your own reader. We pulled the raw bytes of the report to see which layer we were looking at, and the answer changes what you should search for in your own markup.

**What we bring.** We ran the check across **441 built pages** of our own and the homepages of **six sites we run**. Entities turn up on both sides of that line; nothing we found is actually broken, and the reason it is not broken is the whole practical point.

- You get the three-step test that works no matter how you read the announcement.
- You learn the difference between an entity that still resolves and one that no longer does.
- You know where Google did and did not document this, with the pages we checked.
- You get a rule you can add to whatever runs before you publish, so it never happens twice.

On this page

1. [What Google actually changed](#changed)
2. [The example that cannot survive being quoted](#quoted)
3. [What double-escaped means, concretely](#double)
4. [The test, in three steps](#test)
5. [441 of our own pages, and six sites we run](#ours)
6. [Where Google documented this: nowhere](#undocumented)
7. [What you need](#need)
8. [What this does not break](#not)
9. [Before and now, in a table](#table)
10. [The words, in a table](#words)
11. [Where you stand, in three thresholds](#thresholds)
12. [Questions nobody has actually asked us](#faq)

Structured data is the one part of a page written for machines only. Nobody proofreads it, nothing on screen changes when it goes wrong, and the failure mode is silent: a price with stray characters in it, a product name that reads like a corrupted file. This is a change that produces exactly that kind of failure, announced in exactly the place least likely to reach the people it affects.

## What Google actually changed

JSON-LD extraction is the step where Google takes the text inside a <script type="application/ld+json"> tag and turns it into the fields it uses for rich results — a price, a rating, a set of FAQ answers.

Google's words, reported on 21 August 2026: *"To bring our parser up to JSON and other standards, we changed our JSON-LD extraction and are now only applying a single pass of HTML unescaping."* Gary Illyes added a pointer rather than an explanation: *"If you're wondering what *proper* escaping is in JSON, I have good news for you! It's very, very well defined in RFC 8259, specifically section 7."*

Two passes became one. That is the entire change, and everything below is a consequence of it.

## The example that cannot survive being quoted

Google illustrated the consequence with a sentence that has been reproduced everywhere: double-escaped entities will no longer be unrolled, with two examples in brackets.

Here is the problem with reading that sentence anywhere other than the original. The examples are entity sequences, and an entity sequence changes shape every time it passes through something that escapes text. Google's post is one layer. The site that reported it is a second — and that site happens to publish its article body inside its own JSON-LD, which is a third.

So we did the only thing that resolves it: we fetched the raw bytes of the report instead of the rendered page. In the source, the first example is written &amp;amp;. Decode that once, which is what the reader's browser does, and it becomes &amp; on screen.

If you read the rendered sentence and go looking for &amp; in your own markup, you will find it on a great many sites — and almost all of those instances are fine. Single-escaped entities still resolve under one pass. Searching for them produces a long list of false alarms and hides the short list that matters. The thing worth finding is an entity that is still an entity *after* one round of unescaping.

## What double-escaped means, concretely

Four ways to write the same product name, and what each becomes now:

Only the first line changed behaviour on 21 August. It used to survive because two passes unrolled it all the way down; with one pass it stops halfway and the literal characters end up in the value. A shop with that markup now has a product called Fish &amp; Chips in Google's index, and nothing on the page looks different.

The second line still works, and this is where honesty is worth more than a scare. It works because Google still does one pass of HTML unescaping — a courtesy, not a standard. Google's own remedy points away from it: use *"standard JSON escapes or Unicode hexadecimal escapes"*. HTML entities were never the JSON way of writing a special character; they worked because the parser was forgiving, and the announcement is about the parser being less forgiving than it was.

## The test, in three steps

This works regardless of which layer of escaping you happened to read the announcement through, which is the point of writing it down as steps rather than as a string to search for.

1. **Extract the block.** View source, take everything between the opening and closing script tags of the JSON-LD block. Not the rendered page — the source.
2. **Does it parse as JSON?** Paste it into any JSON validator. If it fails here, you have a problem that predates this change and costs you every rich result on the page.
3. **Unescape it once, then look again.** Any entity sequence still present after a single unescaping pass was double-escaped, and that one is now broken.

Step three is the one nobody does, and it is the only step that distinguishes the two cases. It is also trivial to automate, which is what we did.

*Every drawer has a slot for a label describing what is inside. Structured data is that slot, and this change is about what happens when the label itself has been written twice.*

## 441 of our own pages, and six sites we run

We ran the check on 26 August 2026 against every built page of cittago.com that emits structured data. Result: **441 pages, 441 JSON-LD blocks, zero that failed to parse, and six entity sequences spread across three of them.**

All six are single-escaped, so all six still resolve, and none of the three pages is broken. That is the same verdict we reach about a client site further down, arrived at from the opposite direction — and we would rather report it against ourselves first. Two of the three are our own Italian articles, where an &Egrave; and an &eacute; were typed into FAQ text by hand and travelled from the content file into the generated markup. The third is a client landing page served from our domain.

We are publishing this rather than quietly fixing it first, because an audit that only gets reported once it is clean is not an audit, it is a press release. The distinction that matters is where the entities came from: the generator did not invent them. Markup built from data rather than assembled out of pre-escaped strings cannot produce a double escape on its own. What it can do is carry through an entity a human typed into the content — which is precisely the route by which most sites acquire the untidy version, and, one careless layer later, the broken one.

Six harmless sequences and no parse failures across 441 pages is not luck. It is what a parse-and-entity check running before every publish buys you: an announcement posted to LinkedIn on a Friday cost us nothing by Monday, because the test had been running long before it, and the worst it found was untidy rather than wrong. That unglamorous half is the part of [the SEO and AI search work we do from Cluj-Napoca](https://cittago.com/services/seo-ai-search/) that keeps paying.

The other half of the check is outside our own site. We checked the homepages of six sites we administer — the selection rule being simply that we run them — and counted JSON-LD blocks, parse failures and entity sequences:

Seven sequences on one site: five instances of an ampersand entity inside avatar URLs, and two of a dash entity inside the page title. Every one of them single-escaped. Which means — and this is the part a hurried reading would have got wrong — **that site is not broken.** One pass resolves all seven. Had we stopped at "it contains entities, therefore it is affected", we would have opened a ticket against a plugin that is behaving acceptably.

The reason it is a WordPress site is not a coincidence and is not an indictment either. Plugins that assemble JSON-LD by concatenating strings that were already HTML-escaped for display are the classic route to double escaping. This one escapes once, which is untidy and currently harmless.

## Where Google documented this: nowhere

An announcement on a social network is not documentation, so we went looking for the real thing. On 24 August 2026 we fetched five Google properties and searched each for *unescap*, *single pass*, *double-escaped*, *RFC 8259* and *escape*:

- the Search Central documentation updates page;
- the introduction to structured data markup;
- the general structured data guidelines;
- the page on generating structured data with JavaScript;
- the Search Central blog index.

Zero hits, on all five, for all five terms. To be sure we were reading content rather than an empty shell rendered by JavaScript, we ran control terms we knew had to be present — the structured data introduction returned 64 instances of "structured data" and 7 of "JSON-LD"; the updates page returned 144 and 8. The pages were real. The change is simply not in them.

We are stating an absence, so we are stating its boundaries too: we checked five properties on one date. Google may document it later, may have documented it somewhere we did not look, and the help centre is large. We re-ran the search on the morning of 26 August against four of the five — the updates page, the structured data introduction, the general guidelines and the JavaScript page — and the count was still zero. What we can say is that on 26 August 2026 a developer looking for this in the obvious places will not find it.

## What you need

- **The page source, not the rendered page.** Every browser dev tool shows you a normalised version of the DOM; entity sequences are exactly what normalisation hides. Use view-source or a plain HTTP request.
- **A JSON validator.** Any one. Step two catches more real problems than step three.
- **One representative page per template.** Product, article, service, homepage. Structured data is generated per template, so one sample of each covers a site of any size.
- **Somewhere to put the check permanently.** Ours runs over the built site before anything is published. Adding it took an afternoon and it has now paid for itself twice.

## What this does not break

*Lined up rather than nested, the set stops being a puzzle. That is what validating a block does to markup: it makes the layers countable.*

- **It does not break single-escaped entities.** One pass still resolves them. They remain untidy rather than urgent.
- **It does not break plain characters.** An ampersand written as itself in JSON is correct and always was.
- **It does not touch Microdata or RDFa.** Those live in the HTML body, where the browser's own parser handles entities. Google's statement was about JSON-LD extraction specifically, and said nothing about the others.
- **It does not remove your pages from the index.** Structured data is an enhancement, not a requirement. What you lose is the enhancement, on the field that was mangled.
- **It does not announce itself.** No warning, no email, no error. A wrong value is still a valid field, which is why the check has to be something you run rather than something you wait for.

## Before and now, in a table

## The words, in a table

## Where you stand, in three thresholds

**First threshold** — you do not know whether your site emits structured data at all. Then this change cannot hurt you, and the useful move is unrelated to it: a page with no structured data is invisible to every enhancement Google offers, which is a bigger gap than the one this article describes.

**Second threshold** — you have structured data from a plugin or a theme and have never looked at it. Take one page per template through the three steps. Expect step two to be clean and step three to be clean too; if either is not, you have found something worth more than the hour it cost.

**Third threshold** — your markup is generated by your own code. Then the fix is not a fix, it is a test: assert that every JSON-LD block parses and that none contains an entity after one pass, and run it before every publish. That is where ours lives, and it is why the audit above was boring.

If structured data is part of how you expect to be found by AI assistants rather than only by search, that is a different conversation and we have written it separately — see [getting cited by AI search](https://cittago.com/blog/get-cited-by-ai-search/) and [llms.txt and cats.txt](https://cittago.com/blog/llms-txt-cats-txt-2026/).

## Questions nobody has actually asked us

None of these arrived by email. They are the questions we had to answer ourselves in order to write the article, and the answers are short because the announcement was short.

Last updated: 26 August 2026. The quotations attributed to Google and to Gary Illyes come from the Search Engine Roundtable report of 21 August 2026, which cites a Google post on LinkedIn; we did not read the LinkedIn post itself, and we say so because the difference matters for a change that has no other public record. The escaping analysis of the example was done on the raw bytes of that report, fetched on 24 August 2026, not on its rendered text. The audit of built pages was re-run on 26 August 2026 against a fresh static build of cittago.com: 441 pages, 441 blocks, zero parse failures, six single-escaped entity sequences on three pages. An earlier run on 24 August reported 435 pages and no entities; we could not reproduce that entity count on 26 August, so the figures above are the 26 August ones and the earlier ones are withdrawn. The six-site check was run the same day, one HTTP request per homepage, reading raw source. The search of Google's own properties was run on 24 August 2026 across five URLs, with control terms confirming the pages had rendered; we checked five properties on one date and claim nothing beyond that. We will update this page if Google documents the change, or if it clarifies whether a single pass of HTML unescaping is permanent.

Sources: [Search Engine Roundtable — JSON-LD Extraction For Googlebot Now Does One Pass Of HTML Unescaping (21 August 2026)](https://www.seroundtable.com/json-ld-extraction-googlebot-41921.html) · [RFC 8259, section 7 — String escaping in JSON](https://www.rfc-editor.org/rfc/rfc8259#section-7) · [Google Search Central — Intro to how structured data markup works](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data)

*One request per homepage, 24 August 2026, reading the raw source rather than a rendered page. Entity counts are of sequences present in the JSON-LD before any unescaping.*

| Site | JSON-LD blocks | Failed to parse | Entity sequences |
| --- | --- | --- | --- |
| five of the six | 1 each, one site 0 | 0 | 0 |
| one WordPress site | 1 | 0 | **7** |

*The four ways an ampersand can be written inside JSON-LD, and what Google's extractor produces from each after the change reported on 21 August 2026.*

| Written in the markup as | Before | Now |
| --- | --- | --- |
| plain & | & | & — unchanged, correct |
| \u0026 | & | & — unchanged, correct |
| single-escaped &amp; | & | & — unchanged, still resolves |
| double-escaped &amp;amp; | & | **&amp; — literal, wrong** |

*The vocabulary needed to read the announcement without guessing. Definitions are ours, drawn from RFC 8259 and from the announcement itself.*

| Term | What it means |
| --- | --- |
| JSON-LD | Structured data written as a JSON object inside a script tag. The format Google recommends, and the only one this change touches. |
| HTML entity | A way of writing a character that would otherwise be special in HTML, such as an ampersand or an angle bracket. It has no standing inside JSON. |
| Escaping pass | One round of converting entity sequences back into the characters they stand for. Google used to run two; it now runs one. |
| Double-escaped | A character escaped twice, so that it needs two passes to come back. These are the ones that changed behaviour. |
| JSON escape | The way JSON itself writes special characters: a backslash and a letter, or a backslash-u and four hexadecimal digits. Defined in RFC 8259, section 7. |
| Rich result | The extra detail Google can show under a result — stars, a price, an FAQ. It is built from these fields, which is why a mangled one is visible to everyone but you. |

## Questions and answers

**Does this break my rich results?**

Only if your JSON-LD contains entities that need more than one unescaping pass. A single-escaped entity still resolves under the new behaviour. A double-escaped one now survives into the value as literal characters, and whatever field it lands in becomes wrong — a price, a name, a date.

**How do I check my own page in two minutes?**

View source, find the block inside script type=application/ld+json, and paste it into any JSON validator. If it does not parse, you have a problem regardless of this change. If it parses, unescape it once and look for leftover entity sequences: whatever is still there was double-escaped.

**Is an entity in JSON-LD wrong even if it still works?**

Google's own remedy suggests yes. It tells you to use “standard JSON escapes or Unicode hexadecimal escapes”, which are the JSON way of writing special characters. HTML entities were never the JSON way; they worked because the parser was forgiving. It is less forgiving now.

**Where did Google announce this?**

On LinkedIn, reported on 21 August 2026 by Search Engine Roundtable. We looked for it on five Google properties — the Search Central updates page, the structured data introduction, the general guidelines, the JavaScript generation page and the Search Central blog — and found no mention of it on any of them.

**What is RFC 8259 and why does Gary Illyes point at it?**

It is the specification that defines JSON. Section 7 is the part that says exactly how strings escape special characters: a backslash followed by a letter, or a backslash-u followed by four hexadecimal digits. Pointing at it is a polite way of saying that the rules were never ambiguous.

**My site is on WordPress. Am I affected?**

Possibly, and it depends on the plugin rather than on WordPress. Plugins that build JSON-LD by concatenating strings that were already HTML-escaped are the classic source of double escaping. One of the WordPress sites we run carries seven entity sequences in its JSON-LD; all seven are single-escaped, so all seven still resolve.

**Should I fix single-escaped entities anyway?**

If it costs you a configuration change, yes. If it means rewriting a plugin you do not control, measure first: they work today. What is worth doing immediately is adding the check to whatever runs before you publish, so a double-escaped one never reaches production unnoticed.

**Will Google Search Console tell me if this breaks?**

Not directly, and that is the uncomfortable part. A field with a mangled value is still a valid field. The rich results test will show you the value Google extracted, which is the fastest way to see the damage — but you have to look, because nothing raises a flag.

**Does this affect Microdata or RDFa?**

The announcement is about JSON-LD extraction specifically. Microdata and RDFa live in the HTML body, where the browser's own parser handles entities, so the mechanism described here does not apply to them in the same way. Google did not say anything about them either way.

**What is the smallest thing I can do today?**

Take one page — the most valuable one, usually a product or a service page — and validate its JSON-LD as JSON. That single check catches both this change and every malformed-markup problem that predates it, and it takes about a minute.

---

Cittago · https://cittago.com · digital marketing, SEO, AI search, Google Ads and web development for small and medium companies in Romania, Italy and the EU.
