Does your sitemap or feed still use XSLT?
Chrome stops running XSLT on Nov 17, 2026. Enter the address of a sitemap, RSS or Atom feed and see in a few seconds whether it will show as raw XML.
Last updated: · What changed: Added an accuracy table, coverage statement and Chrome 158 sourcing, and a new operator section on the About page.
What the three answers mean
- Will break after Nov 17, 2026
- The file has an
xml-stylesheetline for an XSLT file. Browsers that drop XSLT will show the XML tree instead of your styled page. The checker lists the exact line and the steps to fix it. - Safe (CSS stylesheet)
- The stylesheet line points to a CSS file. Chrome keeps supporting
type="text/css"on XML, so nothing changes. - No stylesheet
- The file has no stylesheet line. Raw XML is what browsers show for it today and after the change, which is normal for most feeds.
The dates
XSLT stops working in Chrome Stable for everyone except Origin Trial and Enterprise Policy participants (Chrome 158).
The Origin Trial and the Enterprise Policy end and XSLT is off for all users (Chrome 176).
Dates and version numbers as listed on the official Chrome page on deprecating XSLT and the Chrome Platform Status entry, read October 2026. Some early reports said Chrome 155; Chrome's current documentation and Platform Status entry say Chrome 158, with the same November 17, 2026 date. More on what is affected.
How this checker decides
The checker is a text analyser, not a browser. It requests the address you enter, reads the start of the response and applies the same rules every time. These are the rules and their edge cases, as the code applies them today.
What it fetches
- One plain GET request with the user agent
XSLTCheckerBot/1.0, no cookies and no credentials. Only publichttp://andhttps://addresses on ports 80 and 443 are allowed. - Redirects: followed by hand, at most three, and every hop is checked again against the same address rules. A redirect to a private or reserved address stops the check.
- Time and size: the whole chain has a six-second deadline, and at most 1.5 MB of the body is read. If the file is bigger, the result is marked truncated and the well-formedness check is skipped, but the prolog, where the stylesheet line lives, is still read.
- Content types: XML, HTML and plain text are read. Anything else is refused, including compressed files: a
sitemap.xml.gzis not unpacked, so check its uncompressed address instead.
Which stylesheet lines count
Only xml-stylesheet processing instructions in the prolog, before the root element, are read, which is where browsers look. A comment or DOCTYPE before them is skipped; a line inside the document body is ignored. The target must be written in lower case, as xml-stylesheet; a different case is still listed, with a note that browsers may already ignore it.
Each line is then classified from its type value, ignoring case and anything after a semicolon:
text/cssis CSS, whatever the file is called. CSS is not being removed.text/xsl,application/xslt+xml,text/xslt,application/xslandapplication/xsl+xmlare XSLT.- With any other or no type, an
hrefending in.xsl,.xsltor.xslt.xmlcounts as XSLT, and a file ending in.csswith no type counts as CSS.
The verdict follows from that list: any XSLT line gives “Will break after Nov 17, 2026”, even if a CSS line is also present. Otherwise any CSS line gives “Safe (CSS stylesheet)”, and no line gives “No stylesheet”. An HTML page, JSON or plain text is reported as not XML; for an HTML page the checker only notes if its source mentions XSLTProcessor, and it does not fetch the scripts the page loads.
Sitemaps, indexes and feeds
The root element tells the kinds apart: urlset is a sitemap, sitemapindex a sitemap index, rss or rdf an RSS feed and feed an Atom feed. The kind selects the fix steps, such as the sitemap or feed CSS generator, and helps recognise common plugins. A sitemap index is checked as a single file: its child sitemaps are not opened, and each one can have a stylesheet of its own. The robots.txt option reads the Sitemap: lines and checks up to five of them; the Batch Pack checks up to 200 addresses.
The XSL file and what it loads
With “Fetch and inspect the stylesheet” on, the first XSLT line is resolved against the final address and fetched under the same limits, with at most six stylesheet fetches per request. The checker reports its size, its version, the output method and any extension namespaces such as EXSLT or Saxon. It lists the xsl:import and xsl:include files it finds and flags document() calls found in the text. It does not fetch those imported, included or document() files, so a problem inside them will not show. A dynamically built document() address may not be flagged.
What is stored about your URL
Nothing about the address or the file. The server fetches it, answers and discards both. The event log keeps a record that a check happened with its outcome only, such as “break”, “safe” or an error code, plus the page path, a random visitor id, the referrer, campaign tags, country and a rough device type. A one-way hash of your network address, combined with a secret, feeds a daily counter that enforces the free limit. See the privacy page.
A server can answer our crawler differently from a browser, and the checker does not run scripts, so treat a result as a strong hint and confirm in a browser for important files.
What the removal does and does not affect
In general terms, the change concerns the browser acting as a viewer. When a person opens an XML file in Chrome and the file points to an XSLT stylesheet, the browser used to turn it into a styled page. After the removal it shows the plain XML tree. Likewise, a page script that creates an XSLTProcessor loses that class.
- Not affected: programs that fetch and parse the raw XML. This includes search engine sitemap fetchers and feed readers, which read the URLs, dates and items and have never needed the stylesheet.
- Not affected: the file itself. A sitemap or feed with a stylesheet line is still valid XML, and so is one without it. Removing the line does not change the data.
- Not affected: XML shown with
type="text/css", and transforms done on a server or at build time. - Affected: people who open the address in a browser, and any web app that calls
XSLTProcessorin script.
Chrome gives its reasons on its own page: XSLT is used by about 0.02% of page loads and the XSLT processing instruction by less than 0.001%, and the aging libxslt code is a security concern. Details and dates are on the official Chrome page on deprecating XSLT. In short, the question is whether any person needs the styled view. If not, delete the line; if so, pick one of the options below.
Migration options
a) Render HTML on the server or at build time
Run the transform once when you publish, and link the result next to the data. The XML stays clean for crawlers and readers.
xsltproc -o sitemap.html sitemap.xsl sitemap.xml
Publish sitemap.html next to sitemap.xml, link it from your footer if people should find it, and remove the stylesheet line from the XML. More commands are on the migration page.
b) Keep the XSLT working with the official polyfill
The polyfill is a WebAssembly port of libxslt and libxml2 under the BSD-3-Clause licence, published as the npm package xslt-polyfill (the xslt_polyfill repository). Copy xslt-polyfill.min.js to your own site and add one element inside the XML root:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<script src="xslt-polyfill.min.js" xmlns="http://www.w3.org/1999/xhtml"></script>
<url>...</url>
</urlset>
Any external resource it needs is loaded with fetch(), so cross-origin rules (CORS) apply. An extra element in a sitemap is not part of the sitemap schema; we have not tested how every consumer treats it, so if in doubt, use the polyfill on a copy meant for people only. Read the self-hosting guide for size and CSP details.
c) RSS and Atom: advertise the feed from HTML
Readers find a feed through autodiscovery in an HTML page, so people do not have to open the raw file.
<link rel="alternate" type="application/rss+xml" title="Example Blog" href="/feed.xml">
Put this in the head of your pages and link visitors to a normal HTML archive, not to the raw feed address.
d) Switch to CSS when you only need styling
Replace the XSLT line with a CSS one. It works with sitemaps and feeds, and Chrome keeps supporting it.
<?xml-stylesheet type="text/css" href="/feed.css"?>
The sitemap and feed generators write the CSS file and the exact line.
e) JSON and client-side rendering for API-like XML
If the XML is an API response that a page turns into HTML, serve JSON instead, or parse the XML with DOMParser, and build the markup in script. Escape any text you insert.
const items = await (await fetch('/api/items.json')).json();
document.querySelector('#list').innerHTML = items
.map(i => `<li><a href="${encodeURI(i.url)}">${i.title.replace(/[&<]/g, c => c === '&' ? '&' : '<')}</a></li>`)
.join('');
f) SaxonJS for full XSLT 3.0 in JavaScript
For stylesheets that use XSLT 2.0 or 3.0, which libxslt and the polyfill do not run, Saxonica provides SaxonJS. A stylesheet is compiled once to a .sef.json file and run in the browser. Check Saxonica's licence terms for your use.
npm install --save-dev xslt3
npx xslt3 -xsl:feed.xsl -export:feed.sef.json -nogo # compile the stylesheet once
// in the page, after loading Saxonica's SaxonJS browser runtime script:
SaxonJS.transform({ stylesheetLocation: 'feed.sef.json', sourceLocation: 'feed.xml', destination: 'replaceBody' }, 'async');
Find the remaining uses with the Reporting API
Chrome reports XSLT use as a deprecation report with the id XSLT. Run this on a page you control to log where the code still depends on XSLT.
new ReportingObserver((reports) => {
for (const r of reports) {
if (r.body.id === 'XSLT') console.log('XSLT used:', r.body.message, r.body.sourceFile, r.body.lineNumber);
}
}, { types: ['deprecation'], buffered: true }).observe();
Two test cases and the expected verdicts
These two small files show what the rules above give. The same two documents are run through the analyzer in our unit tests, so the verdicts shown are what the code returns. Paste either one at an address you control to try it.
RSS feed with an XSLT line
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/feed.xsl"?>
<rss version="2.0"><channel>
<title>Example Blog</title><link>https://example.org/</link><description>Notes</description>
<item><title>Hello</title><link>https://example.org/hello/</link></item>
</channel></rss>Checker verdict: Will break after Nov 17, 2026
Atom feed with a CSS line
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/feed.css"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Example Blog</title><id>https://example.org/</id><updated>2026-10-01T00:00:00Z</updated>
<entry><title>Hello</title><id>https://example.org/hello/</id><updated>2026-10-01T00:00:00Z</updated></entry>
</feed>Checker verdict: Safe (CSS stylesheet)
How accurate is the checker?
10 of 12 samples matched the expected verdict, generated on . Each row below is a real run: a script feeds a small test file to the same code that answers your check, and the table is built from what it returned. A test re-runs it on every build, so the table cannot drift from the code. The expected verdicts were written first and are not changed to hide misses.
| Sample | Expected | Actual | Result |
|---|---|---|---|
| Sitemap with <?xml-stylesheet type="text/xsl"?> One XSLT processing instruction before the root element | Will break | Will break | Match |
| Sitemap with <?xml-stylesheet type="text/css"?> A CSS stylesheet instruction, no XSLT | Safe (CSS) | Safe (CSS) | Match |
| Sitemap with no stylesheet Plain XML, no processing instruction | No stylesheet | No stylesheet | Match |
| RSS feed with an XSLT stylesheet An RSS 2.0 feed whose XSLT instruction points to rss.xsl | Will break | Will break | Match |
| Address that redirects (301) to the XSLT sitemap A 301 redirect, then the sitemap with an XSLT instruction | Will break | Will break | Match |
| Sitemap whose stylesheet uses xsl:import and xsl:include An XSLT instruction; the stylesheet imports base.xsl and includes parts/header.xsl | Will break, imports listed | Will break, imports listed | Match |
| Sitemap whose stylesheet calls document() An XSLT instruction; the stylesheet loads labels.xml with document() | Will break, document() flagged | Will break, document() flagged | Match |
| HTML page with XSLTProcessor in an inline script A script element that creates new XSLTProcessor() | XSLTProcessor found | XSLTProcessor found | Match |
| HTML page with XSLTProcessor in an external script A script element with src="/assets/transform.js"; that file creates new XSLTProcessor() | XSLTProcessor found | Not XML, no XSLT found Only the HTML of the page is read. Script files linked with src are not fetched, so XSLTProcessor inside them is not seen. | Miss |
| HTML page with no XSLT A normal page with a small inline script that does not use XSLT | Not XML, no XSLT found | Not XML, no XSLT found | Match |
| HTML article that only mentions the word XSLTProcessor The word XSLTProcessor in a paragraph of text; no script uses it | Not XML, no XSLT found | XSLTProcessor found The page text is searched for the word XSLTProcessor, so a page that only writes about it is flagged. It does not check that a script really calls it. | Miss |
| Non-XML address (JSON) A JSON response, content type application/json | Not checked: not XML or HTML | Not checked: not XML or HTML | Match |
These are our own small fixtures, not a survey of real websites, so they show how the rules behave, not how often they are right on the web at large.
What the checker does and does not detect
- Detected:
<?xml-stylesheet?>instructions before the root element of an XML file. Atype="text/xsl"(or another XSLT type, or an .xsl or .xslt file name) is reported as XSLT;type="text/css"is reported as safe and is not flagged. A target not written in lower case is noted. - Detected, in the page itself only: when the address is an HTML page, the page source is searched for the word
XSLTProcessor. That covers inline scripts, and it also matches the word in plain text. - Not detected:
XSLTProcessorin an external script file. Script files linked withsrcare not fetched. The word is not searched for in XML files either. - Listed, not followed: when the XSLT file can be fetched, its
xsl:importandxsl:includeaddresses are listed. The imported files are not fetched or checked, and only the first XSLT stylesheet of a document is opened. - Flagged in that one file: a call to
document()in an attribute of the stylesheet is reported, because it loads other files. Calls inside imported files are not seen. - Not visible to the checker: XSLT run on a server or at build time. The browser only receives the finished output, so it is not affected by the removal and the checker has nothing to find.
- Not reachable: pages behind a login. The checker fetches the address as an anonymous visitor, with no cookies, so it sees the login page or an error instead.
- Not detected: scripts added to a page by other scripts. The checker does not run JavaScript.
Redirects are followed up to three times, and a response that is not XML or HTML (JSON, for example) is reported as not checked.
Fix it without the checker
The checker is the fast route. If you already know the file, these tools work on their own and run in your browser: a CSS stylesheet for a sitemap, a CSS stylesheet for a feed, the XSLT to HTML converter and the XML validator. Checking more than one address at a time is in the Batch Pack; see pricing.
Questions
What does the checker detect, and what does it miss?
It detects xml-stylesheet instructions with an XSLT type before the root element of an XML file, and lists xsl:import and xsl:include addresses of the first stylesheet without opening them. It flags document() calls in that stylesheet. For an HTML page it searches the page source for the word XSLTProcessor, so inline scripts are covered and external script files are not fetched. It cannot see server-side or build-time XSLT (not affected by the Chrome change), pages behind a login, or scripts injected by other scripts. See the accuracy table above for how it did on 12 test samples.
What exactly does the checker look at?
It fetches the address you enter and reads the start of the file. It lists every xml-stylesheet line before the root element, tells XSLT from CSS by the type and the file name, and reports the result. If the line points to an .xsl file it can fetch that file too and report its size, its XSLT version and whether it calls document() or extension functions.
What does “Will break after Nov 17, 2026” mean?
The file asks the browser to run an XSLT stylesheet. Chrome stops doing that on Stable on that date, so a person opening the address will see the plain XML instead of the styled page. Search engines and feed readers read the data, not the stylesheet, so they are not affected.
Why did my check say the file is not XML?
The address returned a page that is HTML, JSON or plain text. A sitemap plugin may redirect to a different address, or the server may answer with an error page. Open the address in a browser and look at what it returns.
Which addresses can I check?
Public http:// and https:// addresses on the normal ports. Addresses that point to private networks, your own machine or cloud metadata services are refused, and redirects are followed at most three times.
Will Google still read my sitemap after Chrome removes XSLT?
The change is in the Chrome browser, not in how sitemaps are fetched. A search engine's sitemap fetcher downloads the raw XML and reads the URLs and dates, so a sitemap that still carries a stylesheet line remains valid XML. Only the page a person sees when opening the sitemap in Chrome changes. Chrome's own documentation does not discuss search engine crawling; this is general information, not a statement from any search engine.
Does the polyfill work for sitemaps opened directly in the browser?
It is designed for that case. You add a script element in the XHTML namespace inside the XML root, serve the script from your own site, and the polyfill applies the stylesheet when a person opens the XML address. Stylesheets and other files it loads are fetched with fetch(), so they must be on the same origin or allow CORS. We have not tested opening a local file from disk.
What about Firefox and Safari?
Mozilla posted an “Intent to Unship: XSLT” in August 2026 (see Mozilla's “Intent to Unship: XSLT” post and the tracking bug). It describes disabling XSLT first in Nightly and then in all channels in August 2027. WebKit, the engine behind Safari, has indicated support for removal, and Chrome's page links to its position. We do not state a date for Safari because none has been published.
How do I test a file before and after I change it?
Run its address through the checker and note the verdict. Make the change, deploy, and check again: a CSS line reads “Safe (CSS stylesheet)” and a removed line reads “No stylesheet”. For the Chrome side, the Reporting API snippet above logs the deprecation report with the id XSLT.
Is it free?
Yes. Checking one address, the converter (up to 500 KB of input), the validator and the CSS generator are free. The Batch Pack ($9, one time) adds list checks, CSV reports, bigger files and batch conversion.