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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Attach a React ref to the rendered Chakra UI element you want to export, wait until its content and assets are ready, then pass that DOM node to html2canvas. The library returns a canvas that you can download as PNG. This captures the rendered element—not the Chakra JSX description—and it reconstructs the image from DOM and CSS rather than copying the browser’s exact pixels.

What you are actually capturing

Chakra components are React abstractions that render ordinary DOM elements. A screenshot library cannot export a component declaration such as <Box p="6" />; it needs the element that exists after React and Chakra have rendered it. Put a ref on that element (or on a wrapper whose contents should be included) and pass ref.current to the capture function.

Confirm ref behavior for the specific Chakra component and the Chakra major version installed in your application. Component APIs, providers, imports and ref forwarding can change between major versions. Chakra’s current installation guidance lists Node.js 20.x as the minimum and uses Emotion at runtime, so match your project’s documented setup rather than copying an older example unchanged.

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

Install and create a basic PNG export

Install the package used by the current html2canvas project documentation:

npm install @html2canvas/html2canvas

The following TypeScript component is a complete browser-side pattern. It captures a Chakra Box, renders at twice the CSS resolution, allows CORS-enabled images, and downloads a PNG.

import { useRef, useState } from "react"
import { Box, Button, Text, VStack } from "@chakra-ui/react"
import html2canvas from "@html2canvas/html2canvas"

export function ShareCard() {
  const cardRef = useRef<HTMLDivElement>(null)
  const [busy, setBusy] = useState(false)

  async function downloadPng() {
    const node = cardRef.current
    if (!node) return

    setBusy(true)
    try {
      const canvas = await html2canvas(node, {
        backgroundColor: null,
        scale: 2,
        useCORS: true,
      })

      canvas.toBlob((blob) => {
        if (!blob) return
        const url = URL.createObjectURL(blob)
        const link = document.createElement("a")
        link.href = url
        link.download = "share-card.png"
        link.click()
        URL.revokeObjectURL(url)
      }, "image/png")
    } finally {
      setBusy(false)
    }
  }

  return (
    <VStack align="stretch" gap="4">
      <Box
        ref={cardRef}
        p="6"
        bg="white"
        color="black"
        borderRadius="lg"
        boxShadow="md"
      >
        <Text fontSize="2xl" fontWeight="bold">Share card</Text>
        <Text>Rendered by Chakra UI and exported from the browser.</Text>
      </Box>
      <Button onClick={downloadPng} disabled={busy}>
        {busy ? "Preparing…" : "Download PNG"}
      </Button>
    </VStack>
  )
}

Call this function only in the browser. The null check handles a click before the ref is attached, and the toBlob callback avoids creating a download until an image blob exists. If your installed package exposes a different import path or your component does not forward refs to the expected element, follow that version’s package and component documentation.

Make the output match the intended design

Background and transparency

backgroundColor: null preserves transparency where the captured element has no painted background. Use a CSS color such as "white" when a solid output is required. A transparent result can look different from the page if the page’s background is outside the captured node.

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

Resolution and dimensions

scale controls the rendered canvas density. A value of 2 produces more pixels than the default and is useful for high-density displays, but it also increases memory use and output size. The options width and height can set capture dimensions; viewport options can establish the layout viewport used while the cloned document is painted. Do not confuse CSS size with pixel size: a scaled canvas can contain more pixels while representing the same on-screen dimensions.

Full content versus a single element

Pass the exact element whose visible bounds should be exported. For a card inside a page, attach the ref to the card rather than to the page shell. If a long component must include content outside its current viewport, make sure its layout has the required height before capture and use the dimension options when necessary.

Adjusting the cloned document

html2canvas clones the document before painting it. Its onclone option lets you modify that clone without changing the live interface—for example, hide an export-only control or apply a temporary class. This is useful for capture-specific presentation, but it cannot add support for CSS features the renderer does not implement.

Wait for React, images and fonts

A ref only proves that the element exists; it does not prove that asynchronous content has finished. Trigger capture after the component is visible and after data, images and fonts needed by the design have loaded. Otherwise the exported image can contain missing images, fallback fonts or an intermediate loading state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Render the component before enabling the export button.
  • For images you control, wait for their load event or otherwise ensure they are complete.
  • Load the font used by the card before capture so text metrics are stable.
  • For charts or animations, capture a settled state and pause motion if a deterministic image matters.

There is no universal React readiness hook supplied by the reviewed documentation; choose a readiness condition appropriate to your component.

Why the result may differ from the browser

html2canvas reconstructs an image from DOM and style information. Its documentation cautions that the screenshot “may not be 100% accurate to the real representation” because it is built from information available on the page. Unsupported CSS, complex effects, font rendering and browser-specific behavior can therefore produce a result that differs from what you see.

When evaluating another approach, compare the requirements that matter for your component:

Requirement Question to answer
CSS fidelity Does the method reproduce the CSS features used by the component?
External assets Can it read the images and fonts, and are the required CORS headers present?
Iframes Does the capture need content inside a same-origin or cross-origin frame?
Output Do you need PNG, another image format, a specific size or a PDF?
Runtime Must the capture happen in the user’s browser, or can it run on a server?

Images, CORS and tainted canvases

An image can display normally in your page and still be unusable for canvas export. If an image comes from another origin, the image server must grant the required CORS access, or you must retrieve it through a controlled proxy. Set useCORS: true when the asset host sends the appropriate CORS headers; the option does not create those headers.

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

If a cross-origin image is drawn without approval, the canvas becomes tainted. Browser security then causes toBlob() or toDataURL() to fail with a SecurityError. The allowTaint option does not make a tainted canvas exportable. Practical fixes are:

  • Serve the asset from the same origin as the React app.
  • Configure the asset host to return the required CORS headers.
  • Use a carefully controlled proxy that retrieves the asset and serves it with suitable headers.
  • Replace an inaccessible remote asset with an approved local copy.

Do not treat a CORS flag as a workaround for an asset server that refuses cross-origin access.

Iframes and browser security

html2canvas supports same-origin iframe content, but a cross-origin iframe cannot be read because the browser blocks access to its contentDocument. The fact that the frame is visibly embedded does not change that rule. If you own the iframe rendering context, Chakra’s EnvironmentProvider can direct DOM-dependent behavior to that iframe’s document. It still cannot grant access to a third-party cross-origin frame.

Useful html2canvas options

  • backgroundColor: choose a solid color or null for transparency.
  • scale: increase or reduce output pixel density.
  • width and height: control capture dimensions.
  • Viewport settings: control the layout viewport used for the cloned page.
  • useCORS: request CORS-enabled loading for eligible images.
  • proxy: route asset retrieval through a proxy when your architecture permits it.
  • onclone: alter the cloned document for export-only changes.

These settings tune dimensions and loading behavior; they do not make unsupported CSS render exactly or bypass browser same-origin protections.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting checklist

The download is blank or missing content

Check that ref.current is not null, the element is visible, and asynchronous data, images and fonts have finished loading. Capture after the settled render rather than immediately after changing state.

toBlob() throws a security error

Look for images loaded from another origin. Confirm the image response has the required CORS headers, move the asset to the app’s origin, or use a controlled proxy. allowTaint is not a fix.

Remote images are absent

Enable useCORS only when the remote host supports CORS, then inspect the browser network response. If the host does not grant access, use a same-origin asset or proxy.

The result does not match the page

Review unsupported CSS, fonts, effects and animation. Simplify the export styling, use onclone for a capture-specific class, and compare the required fidelity against a browser or server screenshot workflow.

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

An iframe is empty

Same-origin iframe content may be accessible; cross-origin content is blocked by browser security. You cannot solve that limitation with a React ref or html2canvas option.

The package or import fails

Verify the installed package name and import shown by your package manager, then check that your Chakra imports and ref behavior match the major version used by the application.

Or skip the browser setup

For a server-side screenshot of a public URL, ScreenshotNeo provides a single-request API. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. It also offers an MCP server with take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

Use the API for a deployed page or a URL that renders your component:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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}`);

See the parameter reference and capture options in the ScreenshotNeo documentation. The service supports full-page and element capture, device presets, custom viewports, retina scale, dark mode, PDF settings, custom CSS and JavaScript, clicks, selector waits, delays, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameters used by other screenshot APIs also work for easier migration.

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account to try it.

Choosing the right workflow

  • Use html2canvas when the capture belongs in the user’s browser and DOM-level fidelity is sufficient.
  • Resolve CORS and iframe ownership before designing the export UI.
  • Use a server screenshot workflow when you need a deployed page, repeatable automation, PDF output or an AI-agent integration.
  • Test the exact Chakra version, component ref behavior, assets and CSS used by your application; no generic capture setting guarantees pixel identity.

Frequently Asked Questions

Can I pass a Chakra component directly to html2canvas?

No. Capture the rendered DOM element reached through a React ref, such as the element rendered by a Chakra Box or a wrapper around the component.

Does useCORS download any remote image automatically?

No. The remote server must permit cross-origin access, or the asset must be same-origin or served through a suitable proxy.

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

Can html2canvas capture a third-party iframe?

No. Browser same-origin rules prevent access to cross-origin iframe documents, even when the frame is visible.

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.