Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The error SecurityError: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules usually means the browser blocked html-to-image from inspecting a stylesheet because of its origin—not that the CSS has invalid syntax. Find the sheet named in the error, check how it was loaded, and then either restore access for that stylesheet or bypass font discovery with an option supported by your installed html-to-image version.

Chrome 64 is the historical context of the original report; the right fix depends on the stylesheet URL, the way the page is served, and the package version. Do not assume that moving all CSS to a server or adding a CORS header to an unrelated endpoint will resolve it.

Why html-to-image throws this error

Browsers restrict access to the CSS Object Model (CSSOM) rules of stylesheets that a page is not allowed to inspect. Reading CSSStyleSheet.cssRules can therefore throw a SecurityError when the sheet is cross-origin or otherwise inaccessible. A Chrome 64-era explanation described this as the browser enforcing origin protections in cases where code had previously appeared to work. That historical guidance recommended using a local development server for CSSOM-dependent functionality; it is a community explanation, not an official Chrome statement. Source: Stack Overflow explanation.

html-to-image may encounter this while preparing fonts, even if the target element appears to use only local styles. Its documented process clones the node, copies computed styles, discovers and embeds web fonts by inspecting @font-face rules, and renders the result. A third-party font stylesheet or widget stylesheet can therefore be the one that fails. The project has reported examples involving cross-origin sheets, including Google Fonts. Project README and documentation; Project issue report.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Diagnose the stylesheet before changing code

  1. Read the complete console error and stack. Record the URL of the stylesheet mentioned, if present, and identify the call in html-to-image that triggered it. A missing or null URL does not by itself identify the cause.
  2. Check the installed package version. Confirm the version in your lockfile or package manager output, then compare its README and TypeScript declarations with the option you intend to use. The project currently documents font-embedding options, but an option in current documentation may not exist in an older installed release. Check the project documentation and types.
  3. Inspect how the stylesheet was loaded. In browser developer tools, check the sheet’s actual URL, response, and request mode. Determine whether it is same-origin, served by a third party, injected by a browser extension, or encountered while testing a local file.
  4. Test the page from HTTP. If you opened the page as file://, serve it through your framework’s local development server and retry. Local-file origin handling differs from an HTTP origin and can interfere with reading CSSOM rules.

Do not assume the visually relevant stylesheet is the culprit. Font discovery can inspect sheets beyond the rules directly attached to the node being captured, so a widget, font provider, or extension-injected sheet may be responsible.

Fix access when the stylesheet needs to be readable

Serve the page through your development server

For a local project, use the normal development command for its framework or server, then open the resulting http://localhost address rather than opening the HTML file directly. This is a diagnostic change as well as a practical fix: it separates a local-file origin problem from a cross-origin stylesheet problem. If the error remains, inspect the named sheet rather than treating HTTP hosting as proof that every stylesheet is readable.

Keep controlled stylesheets same-origin or configure the stylesheet host

If your application controls the stylesheet, prefer serving it from the same origin as the page when practical. Otherwise, configure the stylesheet host and loading setup to grant the requesting origin the appropriate CORS access. Check the actual stylesheet response headers and the browser’s loaded URL; a CORS header on an API, font file, or image endpoint does not automatically grant permission to inspect a separate CSS response.

Changing application JavaScript alone cannot make the browser expose a third party’s protected stylesheet rules. If you do not control that host, ask its operator about supported cross-origin access or choose a conversion path that does not need to inspect that sheet.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use font options only when font discovery is the failing step

These are alternatives to making a stylesheet readable, not interchangeable fixes. Restoring stylesheet access preserves discovery; bypassing discovery can change which fonts are embedded. Confirm the APIs against the installed version’s README and types before relying on them. html-to-image documentation.

Supply font CSS with fontEmbedCSS

The documented fontEmbedCSS option lets you provide the CSS used for font embedding instead of having the library discover and parse font rules from stylesheets. The project also documents getFontEmbedCSS() for obtaining reusable embed CSS. This can help when the blocked sheet is encountered during discovery, provided the supplied CSS contains the font declarations and font data needed for the output.

import { toPng, getFontEmbedCSS } from 'html-to-image';

const node = document.getElementById('capture');
if (!node) throw new Error('Capture target #capture was not found');

const fontEmbedCSS = await getFontEmbedCSS(node);
const dataUrl = await toPng(node, { fontEmbedCSS });

const link = document.createElement('a');
link.download = 'capture.png';
link.href = dataUrl;
link.click();

This example still calls getFontEmbedCSS(), so it is useful only when that call can obtain the font CSS in your setup. If discovery itself throws on the inaccessible sheet, provide the CSS directly or use the deliberate skip option below instead. Check that the imported functions and option are available in your installed release.

Skip font embedding with skipFonts

The documented skipFonts option bypasses font downloading and embedding. Use it only when font embedding is not required for the capture. The browser may render text in a fallback font, changing glyph appearance, line breaks, and layout dimensions; inspect the resulting image before adopting it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { toPng } from 'html-to-image';

const node = document.getElementById('capture');
if (!node) throw new Error('Capture target #capture was not found');

const dataUrl = await toPng(node, { skipFonts: true });

Should you patch html-to-image?

The historical answer to the original report proposed guarding access to stylesheet rules with a presence check. That can avoid some cases where a property is absent, but it does not necessarily help when the cssRules getter exists and throws because access is forbidden. A more relevant compatibility patch catches the access error and skips that stylesheet; doing so may omit font declarations or other information the conversion needs. The original thread is a report and community workaround, not a universal fix. See the original discussion.

If you maintain a patch, pin it to the html-to-image version it changes, document which sheets are skipped, and test the generated output. Avoid treating a catch-all as proof that the capture is correct: it can hide a real font or rendering difference.

Do not rely on an unverified stylesheet filter

A project issue requests a stylesheetFilter option to exclude selected stylesheet origins. A feature request is not evidence that released versions support the option. Check the installed package’s declarations and release documentation before using it; the documented alternatives identified by the project include fontEmbedCSS and skipFonts. Stylesheet-filter issue; Project documentation.

Or skip the browser setup

If your goal is simply to capture a URL as an image or PDF, ScreenshotNeo offers a screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those cleanup steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For example, make one GET request with cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options, response headers, and setup details. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for free and get 1,000 screenshots a month with no card.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common outcomes

Symptom Likely explanation What to try
The error goes away when using the development server The original page was loaded from file://, where local-file origin rules affected CSSOM access. Continue testing from the development server and verify the production origin separately.
The same error names a third-party stylesheet The page may not be permitted to inspect that stylesheet’s rules. Check its response and loading mode. If you control the host, configure appropriate CORS access; otherwise, supply font CSS or skip font embedding if acceptable.
The target looks correct in the browser, but conversion fails Font discovery may inspect a sheet not directly associated with the target’s visible styles. Use the stack and stylesheet URL to identify the failing sheet; test the font-specific options supported by your package version.
The image renders with different text or spacing after using skipFonts The capture is using fallback fonts or different font metrics. Supply embeddable font CSS with fontEmbedCSS or restore access to the required stylesheet, then compare typography and layout.
A suggested stylesheetFilter option has no effect or is rejected The installed release may not implement the feature-requested option. Inspect the package types and release documentation; do not assume an issue proposal is a released API.
Adding a CORS header did not fix the error The header may have been added to the wrong response, or the relevant stylesheet request may not be configured for cross-origin access. Inspect the stylesheet URL, request, and response headers in developer tools; configure the stylesheet host and request setup together.

Frequently asked questions

Does this mean my CSS syntax is invalid?

No. This particular exception concerns permission to read stylesheet rules through CSSOM. A separate CSS syntax problem would need to be diagnosed from its own browser or conversion error.

Can I disable Chrome web security to get past it?

Do not use that as a normal fix. It weakens browser protections and does not repair the behavior users will encounter when the application is deployed.

Will moving every CSS file to my server fix it?

Not necessarily. The failure may involve only one stylesheet, a third-party font provider, a widget, or a local-file test. Identify the actual sheet first; moving unrelated files will not grant access to a protected third-party response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.