Guide · Frontend
Chrome's November 2026 XSLT Removal Explained: What Breaks and How to Migrate
19 min readUpdated By Saket Bhatnagar
Researched and drafted with AI, reviewed and edited by Saket Bhatnagar.
In short
- Chrome XSLT removal, in one line: from Chrome 158, due on 17 November 2026, Chrome stops running XSLT. XSLT is an old language that turns XML data into a web page.
- Two things go: the XSLTProcessor JavaScript class, and the xml-stylesheet line at the top of an XML file that points to an XSLT file. XML itself keeps working.
- Styled RSS and Atom feeds, XML sitemaps that look pretty in a browser, and older in-house apps break. Visitors see raw XML under a 'cannot be formatted' message instead of a page.
- The lasting fix is to run the transform on your server or at build time. A free polyfill (a script that adds back a missing browser feature) works as a stopgap, and two opt-outs last until 17 August 2027.
- Beginners can stop after the build-step fix for the feed. Engineers get what we saw testing Chromium 153: the exact message users see, which stylesheet types count as XSLT, and why Chrome's warning reports stop once XSLT is off.
What goes wrong when Chrome stops running XSLT?
Any page that needs the browser to run XSLT stops looking like a page. A visitor sees a short warning and a wall of raw XML tags, and any script that calls XSLTProcessor throws an error.
The Chrome XSLT removal reaches the stable channel, the version most people use, with Chrome 158 on 17 November 2026. As of 23 October 2026, that is 25 days away.
Picture a common setup. A small engineering blog publishes an RSS feed at feed.xml, so feed readers can pick up new posts. A second file, feed.xsl, makes that feed look like a friendly web page when someone clicks it in a browser. The setup is made up, but the behaviour below is what we saw in a real Chromium build.
Today, Chrome reads feed.xml, sees the stylesheet line, downloads feed.xsl and shows a tidy list of posts. With XSLT turned off, Chrome never downloads feed.xsl. It shows the message 'This document cannot be formatted as intended. It uses XSLT, which the browser does not support.' and the raw feed below it.
Feed readers do not care, because they read the XML directly. The people who suffer are humans who click the feed link, plus any app that built its screens with XSLT inside the browser.
Which words do you need before reading about the XSLT removal?
- XML: a text format that wraps data in named tags, such as an item tag with a title tag inside. RSS feeds, Atom feeds and sitemaps are all XML.
- XSLT: a language for rules that turn one XML document into another document, often HTML. Browsers support only XSLT 1.0, a standard from 1999.
- Processing instruction: a special line at the top of an XML file, marked with question marks, such as xml-stylesheet. It tells the browser which stylesheet to apply.
- XSLTProcessor: the JavaScript class that lets a page run an XSLT transform by hand, for example on XML fetched from an API.
- Origin trial: a Chrome sign-up where a website gets a token that turns a feature on, or keeps an old one alive, for that site only.
- Enterprise policy: a setting that a company's IT team pushes to every managed browser. Here it is called XSLTEnabled.
- Polyfill: a script that adds a feature the browser no longer has, written in JavaScript or WebAssembly (fast compiled code that runs in the browser).
What is the Chrome XSLT removal, and when does it happen?
The Chrome XSLT removal is Google's plan to delete the browser's built-in XSLT engine. Chrome's official page, Removing XSLT for a more secure browser, lists both the XSLTProcessor class and XSLT processing instructions as removed.
Two things stay. XML parsing stays, so fetch, DOMParser and plain XML files still work. An xml-stylesheet line with type text/css also stays, because that applies ordinary CSS rather than XSLT.
| Chrome version | Date | What changes |
|---|---|---|
| 142 | 28 Oct 2025 | Early warning messages appear in the DevTools console |
| 143 | 2 Dec 2025 | Official deprecation, with warnings in the console and Lighthouse |
| 145 on Canary | 2 Dec 2025 | Canary, Dev and Beta builds turn XSLT off by default |
| 146 | 10 Mar 2026 | The XSLTEnabled enterprise policy goes live |
| 152 | 25 Aug 2026 | The origin trial goes live |
| 154 | 22 Sep 2026 | Android WebView Canary, Dev and Beta turn XSLT off by default |
| 158 | 17 Nov 2026 | XSLT stops working on stable, except for origin trial and policy users |
| 176 | 17 Aug 2027 | The origin trial and policy stop working; XSLT is off for everyone |
Why do some posts say Chrome 155 and others Chrome 158?
Chrome 158 is correct, so plan around the date, not the number. Chrome's removal page and release schedule both give 17 November 2026 for Chrome 158.
The mix-up comes from a change in release speed. Chrome's intent to remove XSLT, posted in October 2025, said Chrome 155 for 17 November 2026 and Chrome 164 for 17 August 2027.
Chrome then moved from a release every four weeks to one every two weeks, starting with Chrome 153 on 8 September 2026. In September 2026 the same thread confirmed the new numbers, 158 and 176, which keep the original dates.
If your notes say Chrome 155 or Chrome 164, read them as Chrome 158 and Chrome 176.
What Chrome does with a styled RSS feed, before and after removal
Drag to exploreNotice that the stylesheet is never downloaded once XSLT is off. The feed data is still there, just unstyled, so feed readers keep working.
Diagram connections:
- Visitor clicks feed link to Server sends feed.xml (GET /feed.xml)
- Server sends feed.xml to Is XSLT enabled? (Parse the XML)
- Is XSLT enabled? to Fetch feed.xsl (Yes (stable 157 and older))
- Fetch feed.xsl to Styled HTML page (Run the transform)
- Is XSLT enabled? to Warning plus raw XML (No (Chrome 158 and later))
- Visitor clicks feed link: Browser asks for feed.xml
- Server sends feed.xml: Top lines include xml-stylesheet, text/xsl
- Is XSLT enabled?: Chrome 158+ says no, unless trial or policy
- Fetch feed.xsl: Browser downloads the XSLT rules
- Styled HTML page: Friendly list of posts
- Warning plus raw XML: 'cannot be formatted as intended'
Why is Chrome removing XSLT from the browser?
Chrome says the reason is security. Chrome runs XSLT through libxslt, an open-source C library. The removal page calls such libraries complex, ageing C and C++ codebases with far less security scrutiny than JavaScript engines.
Those libraries have had high-severity bugs. Any website a user visits can call that code, so every user carries the risk. Chrome's page, published in October 2025, says only about 0.02 percent of page loads use XSLT, and under 0.001 percent use processing instructions.
XML is raw ingredients, XSLT is a recipe, and the browser used to be a cook who would follow any recipe a website handed over. Chrome is closing that kitchen, so you cook in your own kitchen, the server, and send finished plates of HTML.
Where the picture breaks: in a real kitchen, a bad recipe only spoils one dish. Here the risk is the old kitchen itself, which a cleverly written recipe can break.
One more difference: feed readers and search engine crawlers still want the raw ingredients. You keep serving the XML to them, and add a cooked HTML page for people.
What breaks after 17 November 2026, and what keeps working?
Anything that needs the browser itself to run XSLT breaks. Anything that only reads or serves XML keeps working, and server-side XSLT is untouched because it never ran in the browser.
| What you have | What users see after removal | Who notices |
|---|---|---|
| Styled RSS or Atom feed with xml-stylesheet | Warning line plus raw XML | People who click the feed link |
| XML sitemap styled for browsers, such as WordPress core sitemaps | Raw XML instead of a table of links | Site owners checking the sitemap |
| Page that calls new XSLTProcessor() | ReferenceError: XSLTProcessor is not defined | Every user of that screen |
| Internal app or device admin page built on XSLT | Blank or raw XML screens | Staff, until IT applies the policy |
| Feed or sitemap read by a crawler or feed reader | No change, the XML is still served | Nobody |
| XSLT run on a server, for example with lxml | No change | Nobody |
| xml-stylesheet with type text/css | No change, CSS still applies | Nobody |
WordPress is worth a check because its core sitemaps, added in WordPress 5.5, write an xml-stylesheet line that points to wp-sitemap.xsl. Search engines read the XML directly, so the main effect is on people viewing the sitemap in a browser.
How do you find XSLT usage before the deadline?
Search your code for the two removed features, then test with XSLT turned off. Do this before 17 November 2026, because the warning signals disappear once XSLT is gone.
Search your code and templates
Look for xml-stylesheet lines of any type except text/css, and for XSLTProcessor in JavaScript or TypeScript. Include CMS themes, PHP templates and feed templates.
Collect reports from real users
Add a small script that listens for Chrome's XSLT deprecation reports and sends them to your logs. The engineer section near the end has a tested snippet.
Turn XSLT off in your own Chrome
Open chrome://flags/#xslt and set it to Disabled, then click through your feeds, sitemaps and old admin screens.
Check Lighthouse and the console
Chrome 142 added early console warnings, and Chrome 143 added the official deprecation warning in the console and Lighthouse.
Ask IT for the legacy report
Chrome Enterprise admins can use the Legacy Technology Report to find deprecated features used across managed browsers.
This grep finds the common forms in a project folder, including PHP and TypeScript files. Drop the exclude-dir option to scan installed dependencies too.
Ignore matches with type text/css. In our Chromium 153 test, text/xsl, text/xml and application/xml all ran as XSLT, so treat every other type as XSLT. Beginners can go straight to the migration section next.
grep -rnIE --exclude-dir=node_modules --exclude='xslt-polyfill*.js' \
'xml-stylesheet|XSLTProcessor' .How do you migrate a styled RSS feed to plain HTML?
Run the same XSLT on your server or in your build, save the result as an HTML page, and keep serving the XML for feed readers. Chrome's removal page suggests this move to the server.
For the blog in our example, the build already writes feed.xml. Add one step that applies feed.xsl and writes feed.html. Your existing XSLT file keeps working, because server libraries still run XSLT 1.0.
The build-time fix: transform once on the server, serve two formats
Drag to exploreNotice that the browser never runs XSLT any more. Feed readers keep the XML; people get real HTML from the same data.
Diagram connections:
- Blog posts to Build step (On each publish)
- Build step to Static host or CDN (Upload both files)
- Static host or CDN to Feed reader (feed.xml)
- Static host or CDN to Chrome 158 visitor (feed.html)
- Blog posts: Source content
- Build step: Writes feed.xml, then runs feed.xsl with lxml
- Static host or CDN: Serves feed.xml and feed.html
- Feed reader: Reads feed.xml, ignores styling
- Chrome 158 visitor: Opens feed.html, a normal page
This Python script is the whole build step. We ran it with lxml 6.1.3, which bundles libxslt 1.1.43, on our sample feed and stylesheet.
# Build step: turn feed.xml into feed.html on the server, once per publish.
# Tested with lxml==6.1.3 (libxslt 1.1.43). Usage: python build_feed_page.py feed.xml feed.xsl feed.html
import sys
from lxml import etree
xml_path, xsl_path, out_path = sys.argv[1:4]
transform = etree.XSLT(etree.parse(xsl_path))
result = transform(etree.parse(xml_path))
if transform.error_log: # xsl:message output also lands here and stops the build
sys.exit(f"XSLT errors, nothing written: {transform.error_log}")
# bytes(result) follows xsl:output and adds a charset meta tag for HTML output.
with open(out_path, "wb") as f:
f.write(b"<!doctype html>\n" + bytes(result))
print("wrote", out_path)Expected output is the line 'wrote feed.html', and the file contains the same heading and links that Chrome rendered natively. It also carries a UTF-8 charset tag, so Hindi titles or a rupee sign display correctly. This needs xsl:output method html in your stylesheet, as in ours. If yours says method xml, change it to html.
Then point people at the page, not the XML. Link to feed.html from your site, and add a link tag with rel alternate and type application/rss+xml in your HTML head so feed readers can still find the feed. Chrome's page recommends that link tag for feeds.
If the stylesheet reports an error, the script writes nothing, prints the error log and exits with code 1. Any xsl:message line counts too, so remove debug messages first.
Beginners can stop here. You know what breaks, how to find it and the lasting fix for a styled feed. The rest is for engineers.
When is the polyfill the right stopgap?
Use the polyfill when you cannot change your build in time, or when people open the raw XML URL directly. It is the xslt-polyfill package, written by Mason Freed, who also posted Chrome's intent to remove XSLT.
It is a WebAssembly build of the same libxslt and libxml2 code, so it supports XSLT 1.0 only. You add one script element, in the XHTML namespace, inside the XML file.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/feed.xsl"?>
<rss version="2.0">
<script src="/xslt-polyfill.min.js" xmlns="http://www.w3.org/1999/xhtml"></script>
<channel>
<title>Example Engineering Blog</title>
...
</channel>
</rss>We tested version 1.0.33 in Chromium 153 with XSLT turned off, and the feed rendered as the styled page again. With native XSLT still on, Chrome transformed the feed itself and the polyfill never ran, which matches the 1.0.33 package README.
- Stylesheet type: the polyfill only reads type text/xsl or application/xslt+xml. If your line says text/xml or application/xml, change it to text/xsl first.
- Size: the 1.0.33 file is 1,456,042 bytes, about 512 KiB after gzip. With type text/xsl, Chromium with XSLT on never fetched it in our tests, but every Chrome 158 visitor will.
- Network rules: the polyfill fetches the stylesheet and any included files with fetch, so cross-origin includes need CORS headers.
- Includes: the README says synchronous XSLTProcessor calls fail when a stylesheet uses xsl:include or xsl:import.
- Pages that call XSLTProcessor: set window.xsltUsePolyfillOnlyIfNeeded to true before the script. In our test, Chromium then kept its native XSLTProcessor while XSLT was still on.
- Download cost on HTML pages: a plain script tag downloads the file in every browser. To avoid that, add the script only when typeof XSLTProcessor is undefined, and wait for its load event before calling XSLTProcessor.
- Feed readers: our feed still parsed cleanly in feedparser 6.0.12 with the script element added. We did not test other readers.
For XML you cannot edit at all, such as a router admin page, Chrome's page points to an XSLT polyfill browser extension. Chrome also shows a banner on such pages that links to an extension search.
How do the origin trial and XSLTEnabled policy buy time until August 2027?
Both keep the old XSLT engine running after 17 November 2026, but only until Chrome 176 on 17 August 2027. Treat them as time to migrate, not as a fix.
The origin trial is for public websites. You register your origin with Chrome's origin trials page and get a token. Chrome's feature entry says the trial runs through Chrome 175.
Chrome's origin trial guide says to send the token on every page, as a meta tag in the HTML head or as an Origin-Trial HTTP response header. A raw feed.xml has no HTML head, so the header is the route for XML files. We could not test a token.
The enterprise policy is for companies with managed browsers. Enabling XSLTEnabled keeps XSLT on for staff, which suits internal tools you cannot rewrite in 25 days. Chrome's page says the policy went live for testing in Chrome 146.
How do you catch XSLT usage from real users with the Reporting API?
Chrome raises a deprecation report when a page uses XSLT, once per page in our test, and a ReportingObserver can catch it. We ran this snippet in Chromium 153 and the server received one beacon with the id XSLT.
const observer = new ReportingObserver((reports) => {
for (const report of reports) {
if (report.body.id === "XSLT") {
navigator.sendBeacon("/xslt-usage", JSON.stringify({
page: location.href,
message: report.body.message,
}));
}
}
}, { types: ["deprecation"], buffered: true });
observer.observe();There is a catch we found in testing. With XSLT turned off, no deprecation report fires at all, and the page simply throws 'XSLTProcessor is not defined'. Collect these reports now, while stable Chrome still runs XSLT.
This snippet also only sees pages that run your JavaScript. A raw XML feed opened directly has no script of yours, so searching your code still matters.
What are Edge, Firefox and Safari doing about XSLT in 2026?
All three browser makers plan to remove XSLT. Chrome has the firmest date, 17 November 2026. Firefox plans August 2027 for all channels, and Edge and Safari have no public date as of 23 October 2026.
Microsoft Edge
Edge is built on Chromium, the open-source base of Chrome. Microsoft's public site-impacting changes page lists the deprecation of XSLT as a future release still to be decided, and says Edge 147 added the XSLTEnabled policy.
Microsoft's policy page says XSLTEnabled works from Edge 147 and is temporary, to be removed in a future version. Edge admins should watch their Microsoft 365 message center for the default-off date.
Firefox
Mozilla posted an Intent to Unship XSLT on 26 August 2026. The plan is to disable it in Nightly as soon as possible, in all channels in August 2027, and then remove the code.
Firefox already has an XSLTEnabled enterprise policy from Firefox 151, and the preference dom.xslt.enabled. The same intent post describes WebKit's position as cautiously supportive.
Safari
We found no published Safari removal date as of 23 October 2026. Plan as if Safari will follow, because the server-side fix works in every browser anyway.
Which migration path should you pick for each case?
Pick the server-side transform for anything you control, and use the polyfill, extension or opt-outs only to cover the gap. This table maps each case to a lasting fix and a short-term cover.
| Case | Lasting fix | Short-term cover |
|---|---|---|
| Styled RSS or Atom feed | Build an HTML page from the feed on the server | Polyfill script inside the XML |
| Browser-friendly sitemap | Drop the styling or render an HTML sitemap | Accept raw XML; crawlers are unaffected |
| Page using XSLTProcessor on API data | Return JSON and render with JavaScript | Polyfill script on the page |
| Internal enterprise app | Move the transform to the app server | XSLTEnabled policy until August 2027 |
| Public site you cannot change in time | Server-side transform | Origin trial until August 2027 |
| Device page you cannot change at all | Ask the vendor for a firmware update | XSLT polyfill browser extension |
If your XSLT uses features beyond version 1.0, Chrome's page also points to SaxonJS, a JavaScript XSLT engine from Saxonica that supports XSLT 3.0. That is a bigger change, so test it like any new dependency.
How do you explain the Chrome XSLT removal in a system design interview?
Frame it as a platform deprecation with a hard date, and show how you would find impact, migrate and keep a rollback. Interviewers listen for a plan that separates machine readers from human readers.
State the change and the date
Chrome 158 removes in-browser XSLT on stable on 17 November 2026, and the last opt-outs end on 17 August 2027.
Separate the readers
Crawlers and feed readers read XML and are safe. Humans viewing XML in a browser and pages calling XSLTProcessor break.
Measure before you change
Search code for the two patterns and collect ReportingObserver deprecation reports while XSLT still works.
Move the work to the server
Run the transform at build time or per request, cache the HTML on a CDN, and keep the XML endpoint unchanged.
Cover the gap
Use the polyfill for pages you cannot rebuild in time, and the enterprise policy for internal tools, each with an end date.
Verify
Test with chrome://flags/#xslt set to Disabled, and check that pages render and the console shows no XSLT errors.
Questions people ask
- Is XML being removed from Chrome too?
- No, only XSLT is removed. Chrome's page says XML itself stays, so fetch, DOMParser, XML files and feeds still work. An xml-stylesheet line with type text/css also keeps working, because it applies CSS, not XSLT. Only the XSLTProcessor class and XSLT processing instructions go.
- Will my RSS feed stop working in feed readers?
- No, feed readers read the XML directly and ignore the stylesheet line. Only people who open the feed URL in Chrome lose the styled view. In our test, the feed with the polyfill script added still parsed in feedparser 6.0.12, though we did not test other readers.
- Does server-side XSLT still work?
- Yes, the removal only affects the XSLT engine inside the browser. Libraries such as lxml in Python run XSLT on your own server and are unaffected. We ran the sample feed transform with lxml 6.1.3 and got the same heading and links that Chrome produced natively.
- Is it Chrome 155 or Chrome 158?
- It is Chrome 158, on 17 November 2026. Chrome's removal page and its release schedule both say so. The October 2025 intent said Chrome 155 and 164, but Chrome moved to two-week releases from Chrome 153. The dates stayed, and the numbers became 158 and 176.
- Can users turn XSLT back on themselves?
- Not in a way you can rely on. Chromium 153 has an Enabled option on the chrome://flags/#xslt page, but asking every visitor to change a flag is not a fix. Chrome's supported routes are the origin trial for websites and the XSLTEnabled policy for managed browsers. Both stop working in Chrome 176 on 17 August 2027.
- How do I check my site is ready?
- Turn XSLT off and click through. Set chrome://flags/#xslt to Disabled, open your feeds, sitemaps and admin screens, and look for the 'cannot be formatted as intended' message or a ReferenceError for XSLTProcessor in the console. If none appear, you are ready.
Sources and further reading
- Chrome for Developers: Removing XSLT for a more secure browser (timeline, migration paths, detection)
- Chrome Platform Status: Deprecate and remove XSLT
- Chrome for Developers: Get features faster with Chrome's two-week release cycle
- Chromium Dash: milestone schedule for Chrome 158
- blink-dev: Intent to Deprecate and Remove XSLT (October 2025, renumbering reply September 2026)
- Chrome for Developers: Get started with origin trials (token delivery)
- Mozilla dev-platform: Intent to Unship XSLT (26 August 2026)
- Firefox enterprise policy reference: XSLTEnabled
- Microsoft Edge: Site compatibility-impacting changes
- Microsoft Edge policy documentation: XSLTEnabled
- xslt-polyfill on GitHub (quoted behaviour is from the README inside the 1.0.33 npm package)
- WordPress developer reference: WP_Sitemaps_Renderer
- lxml documentation: XSLT