Short answer: html2canvas does not take a native screenshot of the browser. It rebuilds an image from the DOM and the CSS properties it has implemented, and its official feature list marks transform as having limited support. First inspect the computed transform and your installed html2canvas version. If the value uses an unrecognised function or 3D geometry that the parser reduces to 2D, simplify the transform only in the capture path or use a browser-rendered capture method when pixel fidelity is essential.
Why a transform can look wrong in html2canvas
html2canvas walks the document, reads styles and content, and paints its own representation onto a canvas. It is therefore not equivalent to asking the browser for a bitmap of the already-rendered page. Any CSS property that has not been implemented, or that is interpreted differently by the library, can produce output that differs from what you see on screen.
The project’s feature list labels transform “Limited support.” Its FAQ explains that every CSS property must be implemented manually, so full CSS coverage is not a design goal. A browser can display a transform correctly while html2canvas omits it, applies only part of it, or positions the resulting pixels unexpectedly.
What the parser actually recognises
The transform parser is function-sensitive. The repository source available at master contains handlers for matrix() and matrix3d(). If a transform function has no handler, parsing stops with an error like Attempting to parse an unsupported transform function "...". That source is not a promise that every released package behaves identically, so always check the version installed in your application.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
| Computed value | What the documented source indicates | Practical meaning |
|---|---|---|
none |
No transform is present in the computed style. | Look for a selector, inline-style, or layout issue rather than transform parsing. |
matrix(a,b,c,d,e,f) |
A six-number 2D matrix handler exists in the examined parser. | Basic 2D transforms may work, but verify rotation, origin, scaling and translation in your exact release. |
matrix3d(...) |
The examined handler extracts selected values and returns a 2D representation; its source comment says general 3D transforms are not supported. | Do not expect perspective, 3D rotation or depth effects to match the browser. |
rotate(...), scale(...), translate(...), or another function token |
Support depends on whether your installed parser recognises that token or has already converted it to a matrix. | Inspect the computed value and test a minimal reproduction instead of assuming the authoring syntax is supported. |
A reproducible diagnosis workflow
- Record the environment. Write down the html2canvas version from
package.jsonornpm ls html2canvas, the browser and version, the operating system, the target element, and the expected versus actual image. The library runs in the browser and depends on browser APIs, so these details matter. - Read the computed style, not just the stylesheet. DevTools can show a friendly declaration such as
rotate: 12deg, whilegetComputedStyle()exposes the value the capture code receives.
const element = document.querySelector('#capture-target');
const style = getComputedStyle(element);
console.log({
transform: style.transform,
transformOrigin: style.transformOrigin,
width: style.width,
height: style.height
});
- Reduce the page to one failing case. Keep the element, its transform, essential dimensions and any image or canvas child. Remove frameworks, animations, filters and unrelated content. A small reproduction makes it possible to tell a parser problem from a resource or layout problem.
- Classify the value. A value of
nonemeans the transform is not reaching the element. A matrix value calls for a geometry comparison. An exception naming an unsupported function points to parser coverage. Amatrix3d()value requires a test for 3D loss rather than a presumption that all transforms fail. - Repeat after disabling animation. Capture only after transitions and keyframes have settled. Otherwise the computed matrix may change between inspection and painting.
Capture without the transform when the geometry is optional
If the transform is decorative and the untransformed layout is acceptable for an export, temporarily change it for the capture and restore it in a finally block. This avoids leaving the live page in a modified state even if html2canvas rejects a resource or throws a parsing error.
async function captureWithoutTransform(selector) {
const element = document.querySelector(selector);
if (!element) throw new Error(`No element matches ${selector}`);
const oldTransform = element.style.getPropertyValue('transform');
const oldPriority = element.style.getPropertyPriority('transform');
const oldOrigin = element.style.getPropertyValue('transform-origin');
const oldOriginPriority = element.style.getPropertyPriority('transform-origin');
element.style.setProperty('transform', 'none', 'important');
element.style.setProperty('transform-origin', 'initial', 'important');
try {
// Wait one frame so layout reflects the temporary style.
await new Promise(requestAnimationFrame);
const canvas = await html2canvas(element, {
backgroundColor: null
});
return canvas;
} finally {
if (oldTransform) {
element.style.setProperty('transform', oldTransform, oldPriority);
} else {
element.style.removeProperty('transform');
}
if (oldOrigin) {
element.style.setProperty('transform-origin', oldOrigin, oldOriginPriority);
} else {
element.style.removeProperty('transform-origin');
}
}
}
captureWithoutTransform('#capture-target').then(canvas => {
document.body.appendChild(canvas);
}).catch(console.error);
This workaround changes geometry: text wrapping, overflow, clipping and the element’s footprint can all move. Compare the result with the intended export, and do not use it when the transformed position is part of the information being communicated. If changing the live DOM is unsafe, render a dedicated export layout whose CSS never applies the problematic transform.
Rank #2
When the transformed pixels must match the browser
Use a capture approach that records the browser’s rendered output rather than reconstructing the page from a subset of CSS. This generally means a browser-automation or other browser-rendering workflow with access to the same fonts, images, scripts, viewport, device scale and authentication state as the page. It has a higher runtime and infrastructure cost than a client-side canvas call, but it avoids asking html2canvas to implement every transform.
| Approach | Visual fidelity | Runtime and deployment | Important constraints |
|---|---|---|---|
| html2canvas with the original styles | Good only for properties and resources it reproduces; transform support is limited. | Runs in the browser with no separate capture service. | Cross-origin images, tainted canvases and cross-origin iframes can independently make output incomplete. |
| html2canvas with a capture-only simplified layout | Predictable for the simplified design, but it intentionally does not represent the transformed geometry. | Low infrastructure cost; requires safe style mutation or a separate export layout. | Layout, clipping and text flow can change. |
| Browser-rendered capture | Best fit when the requirement is the pixels a browser displays, including complex transforms. | Requires browser access, startup time and management of fonts, sessions and resources. | Network failures, authentication, cross-origin policy and sandboxing still apply. |
No single replacement is universally correct. Choose according to fidelity, whether capture can run in a browser, resource and security requirements, and the cost of maintaining a rendering environment.
Rank #3
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Do not confuse resource failures with transform failures
A blank or partly painted canvas is not proof that the transform parser failed. html2canvas documents restrictions around cross-origin images and canvases, and it cannot freely inspect cross-origin iframes. Test the element with images and iframe content removed, then add resources back one at a time. If the simplified element renders, investigate origin headers, image loading and iframe access separately.
The cullOffscreen configuration concerns whether transformed nodes are conservatively painted when off-screen culling is enabled. It is not a switch that adds support for an unrecognised transform function or turns 2D matrix extraction into 3D rendering.
Rank #4
Or skip the browser setup
If you need a screenshot without wiring html2canvas into the page, ScreenshotNeo provides a website screenshot API and MCP server. It captures a URL directly, so your application does not have to reconstruct the DOM in a client-side canvas. Use the endpoint documentation for the full parameter list: ScreenshotNeo API documentation.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Before the capture, ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed as clean shots, and response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
Troubleshooting common symptoms
| Symptom | Likely cause | Action |
|---|---|---|
| An exception names an unsupported transform function. | The installed parser has no handler for that function token. | Test the browser’s computed matrix, replace the transform with a supported 2D representation for export, or use browser-rendered capture. |
| The element appears untransformed. | The computed value is none, the transform was applied to a different element, or the transform is intentionally removed by capture CSS. |
Log getComputedStyle(element).transform and inspect the target node and ancestors. |
| Rotation or scale works, but perspective or 3D depth does not. | The examined matrix3d() path extracts a 2D representation. |
Use a 2D export design or a browser-rendered method; do not infer 3D support from the function name. |
| The canvas is blank or missing images. | Cross-origin image/canvas rules, an inaccessible iframe, a failed request or a page that has not finished loading. | Remove external resources in the minimal reproduction, wait for them explicitly, and resolve origin or iframe access independently. |
| The result changes after a dependency update. | The released package and repository master may differ. |
Record the exact package version, compare the reproduction on that release, and avoid relying on source behavior from another revision. |
| Only content near the viewport is missing. | Off-screen culling or layout changes place content outside the painted region. | Test with culling settings changed, verify the element’s bounding rectangle, and remember that culling does not add transform syntax support. |
Performance, reliability and cost decisions
- Client-side html2canvas: avoids a server round trip and can use the user’s authenticated DOM, but large pages consume browser memory and remain subject to browser security and unsupported CSS.
- Temporary style changes: are inexpensive, yet they trigger layout and can alter wrapping or overflow. Keep the changed interval short and restore styles with
finally. - Browser-rendered capture: spends more time starting or controlling a browser and loading the page, but it is the appropriate direction when transformed pixels are a contractual requirement.
- Remote screenshot API: shifts browser maintenance to a service. With ScreenshotNeo, inspect
X-Page-VerdictandX-Billedto distinguish clean captures from bot checks, blank pages, failed loads and cache hits before treating a response as a successful export.
How to report an unsupported transform
If the behavior appears to be a missing or incomplete property implementation, prepare a minimal test case and open an issue with the project. Include:
Best Value
- the exact html2canvas release and browser version;
- the smallest HTML and CSS that reproduces the result;
- the full computed
transformandtransform-originvalues; - the expected browser rendering and the actual canvas output; and
- whether removing images, canvases and iframes changes the result.
This information lets maintainers distinguish parser coverage from cross-origin, loading and layout conditions, and it avoids assuming that the current repository source describes every published package.
Frequently Asked Questions
Does converting a transform to a matrix guarantee a correct capture?
No. A matrix changes the syntax presented to the parser, but transform origin, clipping, overflow, animation timing and the installed release can still change the result.
Can a dedicated export stylesheet be safer than mutating the live element?
Yes. A separate export layout avoids a visible style flicker and accidental interaction with application state, at the cost of maintaining a second presentation.
Recommended Free Tools
What should be treated as success in an automated pipeline?
Validate the image dimensions and content, not only that a canvas promise resolved; a resolved call can still contain missing resources or simplified geometry.
Quick Recap
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.

