html2canvas Alternatives: Comparing the Top 4 Website Screenshot APIs and Libraries
Compare html2canvas alternatives by fidelity, capture target, browser control, cost and setup, with runnable code and a practical decision guide.
Short answer: choose ScreenshotNeo for a hosted, one-request screenshot of an arbitrary URL; choose html-to-image when you only need to export a DOM node in the current browser; choose Playwright when you need full browser automation and maximum control; choose ScreenshotOne or Urlbox when a hosted URL or HTML capture API fits your workflow. Keep html2canvas when reconstructing a selected element in the visitor’s browser is acceptable.
What html2canvas actually does
html2canvas walks the DOM, reads the style properties it understands and builds a visual representation. It does not take a native browser screenshot, so unsupported CSS, cross-origin images, frames and browser-only rendering behavior can produce differences. The project documentation describes this directly: “it does not actually take a screenshot of the page, but builds a representation of it based on the properties it reads from the DOM.” See the official method documentation and configuration reference.
Use html2canvas when:
- The page is already open in the user’s browser.
- You need one DOM element or a small client-side export.
- Client-side processing and a zero-server setup matter.
Use a real browser capture when the requirement is “what the browser paints”: a complete URL, JavaScript-heavy content, lazy-loaded images, authenticated pages, or repeatable rendering in a backend job.
Decision table: which alternative fits?
| Tool | Capture target | Execution model | Best fit | Main trade-off |
|---|---|---|---|---|
| #1 ScreenshotNeo | URL, HTML, element or full page | Hosted API or MCP server | Production screenshots without browser infrastructure | Requires an API key and service dependency |
| html-to-image | DOM node | Current browser | Client-side exports of a component | Browser support, fonts and cross-origin assets affect output |
| Playwright | Any navigable page | Your automation runtime | Pixel control, scripted interactions and tests | You maintain browsers, workers and retries |
| ScreenshotOne | URL or HTML | Hosted API | Request-based capture with documented GET/POST options | Vendor limits and pricing can change |
| Urlbox | URL | Hosted API | Hosted rendering controls such as headers, cookies and proxies | Verify current plans and capabilities before purchase |
| Browserless | URL, HTML or browser session | Managed or self-hosted browser infrastructure | Screenshotting inside broader Puppeteer/Playwright workflows | More infrastructure than a dedicated image endpoint |
1. html-to-image: closest library replacement for a DOM node
html-to-image clones a target node, copies computed styles, recreates pseudo-elements, embeds fonts and images, serializes the clone into SVG using foreignObject, then can render that SVG through an off-screen canvas. Its README lists current Chrome, Firefox and Safari among tested browsers. Confirm support for your browser, fonts and assets before treating it as a drop-in replacement.
Install and export a node
npm install html-to-image
import { toPng, toJpeg, toSvg } from 'html-to-image';
const node = document.querySelector('#invoice');
if (!node) throw new Error('Missing #invoice');
const pngDataUrl = await toPng(node, {
pixelRatio: 2,
cacheBust: true,
backgroundColor: '#ffffff'
});
const link = document.createElement('a');
link.download = 'invoice.png';
link.href = pngDataUrl;
link.click();
Useful options and edge cases
pixelRatioincreases output resolution but also memory use.- Embed or preload web fonts before capture; otherwise fallback fonts change dimensions.
- Inline or proxy cross-origin images. A failed image can make the export incomplete.
- Use a white
backgroundColorwhen the target contains transparent areas and the output format is JPEG. - Very large nodes can exceed canvas or data-URL limits. Export smaller sections or use a server-side browser.
2. Playwright: full browser control
Playwright’s screenshot API captures viewport or full-page images and can return bytes for storage or pixel-diff processing. It is the strongest fit when a workflow must log in, click controls, wait for application state, set headers, emulate devices or run repeatable visual tests.
Runnable Node.js example
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'page.png', fullPage: true });
await browser.close();
Control before capture
await page.addStyleTag({ content: '.cookie-banner, .chat-widget { display:none !important }' });
await page.locator('button[data-consent="accept"]').click().catch(() => {});
await page.locator('#report').waitFor({ state: 'visible' });
await page.screenshot({ path: 'report.png', clip: await page.locator('#report').boundingBox() });
For reliable jobs, set explicit viewport and timezone values, wait for a meaningful selector instead of an arbitrary sleep, and close the browser in a finally block. Full-page capture can become tall enough to hit memory limits; split long documents when necessary.
3. ScreenshotOne: hosted URL and HTML capture
ScreenshotOne’s API documentation describes a /take endpoint accepting GET or POST requests, including JSON POST bodies. The documentation specifies a maximum request body of 100 MiB. Its product page describes full-page capture that scrolls to trigger lazy-loaded images and other resources, and currently advertises 100 free screenshots per month; recheck quota and pricing before publication or purchase.
curl -G 'https://api.screenshotone.com/take' \
--data-urlencode 'access_key=YOUR_ACCESS_KEY' \
--data-urlencode 'url=https://example.com' \
--data-urlencode 'full_page=true' \
-o screenshot.png
A hosted API removes browser installation and worker maintenance, but you still need to design retries, timeout handling, authentication storage and quota monitoring.
4. Urlbox: hosted rendering controls
Urlbox’s comparison article describes controls for ad and cookie-banner handling, retina quality, proxies, custom headers and cookies, capture delays or events, full-page behavior and user-agent selection. Those are useful comparison axes, but the source is vendor-authored and dated March 21, 2025. It listed Lo-Fi at $19/month for 2,000 screenshots, Hi-Fi at $49/month for 5,000 and Ultra at $99/month for 15,000 at that time; verify current pricing directly.
5. Browserless: managed browsers for broader workflows
Browserless documentation describes managed browser connections for Puppeteer and Playwright, REST endpoints for screenshots and other browser tasks, and hosted or self-hosted deployment. Its screenshot API documents URL or inline HTML input, full-page settings, formats, viewport controls and element selection. Choose it when screenshotting is one step in a larger browser workflow; compare the operational complexity with a dedicated screenshot endpoint for simple captures.
How to choose by capture target
Existing element in your app
Start with html-to-image or html2canvas. They avoid a server round trip and can export a selected component. Test web fonts, pseudo-elements, SVG, filters, cross-origin images and very large dimensions.
Arbitrary public URL
Use ScreenshotNeo, ScreenshotOne or Urlbox for a request-based workflow, or Playwright/Browserless when you need to own the browser steps.
Authenticated or interactive page
Playwright gives direct control over login and actions. Hosted services can also work when they document cookies, headers, user agents, scripts and proxy behavior; confirm those controls before committing.
Visual regression tests
Playwright returns image data suitable for pixel comparison. Freeze viewport, browser version, fonts, timezone, locale and application data to reduce unrelated diffs.
Or skip the browser setup
ScreenshotNeo is the #1 choice for a hosted screenshot API here because it removes capture cleanup, bills only clean shots and has a $5 paid plan for 3,000 shots. One GET request returns PNG, JPEG, WebP or PDF.
Before capture, ScreenshotNeo can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers report the page verdict and whether the shot was billed. It also provides an MCP server for Claude, Cursor and other MCP clients with take_screenshot, get_page_info and capture_pdf.
See the ScreenshotNeo API documentation for all options, including full-page and element capture, dark mode, device presets, retina scale, PDF settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous jobs, webhooks, bulk capture and usage data.
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
Plans include 1,000 shots per month free with no card, Starter at $5 for 3,000, Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000 and Business at $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Create a free ScreenshotNeo account.
Reliability, performance and cost checklist
- Wait for state: prefer a selector, network-idle condition or application signal over a fixed delay.
- Control dimensions: set viewport, device scale, locale and timezone explicitly.
- Handle lazy content: scroll or use a full-page mode that triggers lazy loading.
- Bound work: use navigation and capture timeouts; retry transient failures with backoff.
- Cache safely: cache immutable pages, but reduce TTL when content changes frequently.
- Watch memory: huge full-page images and high retina scales increase CPU, RAM and transfer size.
- Protect secrets: keep API keys, cookies and authorization headers on the server.
- Measure billed work: inspect ScreenshotNeo’s
X-Page-VerdictandX-Billedheaders. - Recheck prices: hosted quotas and plans change; verify vendor pages immediately before purchasing.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Images missing in html2canvas or html-to-image | Cross-origin restrictions or blocked image requests | Serve images with suitable CORS headers, inline them, use a documented proxy, or capture in a real browser. |
| CSS differs from the page | DOM reconstruction does not implement a CSS feature | Use Playwright or a hosted browser capture for native rendering; simplify unsupported styles for DOM export. |
| Web fonts change line breaks | Font has not loaded before capture | Preload fonts and wait for document.fonts.ready before exporting. |
| Blank or partial Playwright image | Capture happened before application rendering | Wait for a stable selector, response, or app-ready marker; inspect console and network errors. |
| Full-page image is enormous | Long page combined with high device scale | Lower scale, capture sections, or generate a PDF instead. |
| Hosted API returns an error | Invalid key, URL, timeout, quota or blocked destination | Check status and response body, validate URL encoding, increase documented timeout limits where available, and retry only transient failures. |
| Cookie banner appears in output | The tool did not detect or dismiss that banner | Use a documented consent option, click a selector, inject CSS, or choose ScreenshotNeo’s consent cleanup. |
FAQ
Is html2canvas a pixel-perfect screenshot tool?
No. It reconstructs from DOM and supported styles, so output can differ from native browser pixels.
Which option is best for one component?
Use html-to-image when the component is in the current browser and its assets are compatible. Use Playwright or a hosted browser when fidelity matters more than client-side simplicity.
Which option avoids running Chromium myself?
A hosted API such as ScreenshotNeo, ScreenshotOne or Urlbox. Browserless is better when you also need managed browser automation.
Can I capture private pages?
Yes, when the chosen workflow supports the required cookies, headers, authorization or login steps. Keep credentials server-side and confirm each provider’s documented behavior.
Should I use a library or an API?
Use a library for an existing DOM node and a hosted or automated browser for arbitrary URLs, JavaScript-heavy pages and repeatable backend jobs.
