The right JavaScript method depends on what you mean by “screenshot.” If you need an image created inside the page, use html2canvas to reconstruct a selected node from its DOM and styles. If you need the browser’s actual rendered pixels—especially in tests, CI, or server-side code—use Playwright’s locator screenshot. Chrome DevTools Protocol (CDP) offers a lower-level clipped capture. These approaches differ in fidelity, security restrictions, runtime, and output format.
Choose the capture method first
| Requirement | Best starting point | Important qualification |
|---|---|---|
| Create an image in an already open web page | html2canvas | It rebuilds the node from readable DOM information; it does not capture native rendered pixels. |
| Capture a test artifact or production browser view | Playwright locator screenshot | The node is scrolled into view and the visible region is captured; overlays and scroll position still matter. |
| Capture a clipped region through a Chromium protocol client | CDP Page.captureScreenshot |
It is a low-level protocol call that returns base64-encoded image data. |
| Render on a server or in Node.js | Playwright or Puppeteer | html2canvas requires browser globals such as window and document. |
For a literal pixel-accurate capture, prefer browser automation. For a lightweight, client-only export button, html2canvas is usually simpler.
Capture one DOM node in the browser with html2canvas
Install the package with npm:
npm install html2canvas
Then select the element, await the generated canvas, and convert it to a downloadable file or a data URL. This complete browser example captures a card with the CSS selector #invoice-card:
import html2canvas from 'html2canvas';
const node = document.querySelector('#invoice-card');
if (!(node instanceof HTMLElement)) {
throw new Error('The element #invoice-card was not found');
}
const canvas = await html2canvas(node, {
backgroundColor: '#ffffff',
scale: window.devicePixelRatio,
useCORS: true
});
canvas.toBlob((blob) => {
if (!blob) {
throw new Error('The canvas could not be converted to an image');
}
const link = document.createElement('a');
link.download = 'invoice-card.png';
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
}, 'image/png');
In a script loaded directly in a page, use the browser build instead:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problems#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
<script src="https://cdn.jsdelivr.net/npm/html2canvas/dist/html2canvas.min.js"></script>
<script>
const node = document.querySelector('.chart-card');
html2canvas(node).then((canvas) => {
document.body.appendChild(canvas);
});
</script>
Download JPEG or WebP instead of PNG
PNG preserves sharp text and transparency. JPEG is smaller for photographic content but does not preserve transparency. WebP can reduce size when your consumers support it.
const canvas = await html2canvas(node, { backgroundColor: null });
canvas.toBlob((blob) => {
if (!blob) return;
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'chart.webp';
a.click();
URL.revokeObjectURL(url);
}, 'image/webp', 0.9);
Get a byte buffer or base64 string
Use toBlob for uploads and toDataURL when an inline string is required. Blob conversion avoids the large in-memory base64 expansion.
const canvas = await html2canvas(node);
const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
if (!blob) throw new Error('No image was produced');
const bytes = new Uint8Array(await blob.arrayBuffer());
await fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'image/png' },
body: bytes
});
const dataUrl = canvas.toDataURL('image/png');
Wait for fonts, images, or a chart before capturing
Call the capture after the relevant resources have finished loading. For web fonts, wait on document.fonts.ready. For images, wait until each image reports complete; an image can be complete but still have failed loading, so check naturalWidth.
await document.fonts.ready;
await Promise.all([...node.querySelectorAll('img')].map((img) => {
if (img.complete) return Promise.resolve();
return new Promise((resolve) => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
const canvas = await html2canvas(node);
What html2canvas can and cannot reproduce
The project explicitly says its “screenshot” is based on the DOM and may not be 100% accurate because it builds an image from information available on the page rather than taking an actual screenshot. Unsupported CSS, browser painting details, filters, blend modes, and complex effects can therefore differ from what the user sees.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Cross-origin images and tainted canvases
Images must be readable under browser origin rules. The html2canvas documentation states that images need to be same-origin unless a proxy helps. Setting useCORS: true requests CORS loading, but the image server must send an appropriate Access-Control-Allow-Origin header; this option cannot bypass security policy.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
const canvas = await html2canvas(node, {
useCORS: true,
allowTaint: false
});
If cross-origin pixels taint the canvas, reading it with toBlob or toDataURL throws a security error. Move the asset to your origin, configure CORS on the asset host, or use a server-side browser capture.
Cross-origin iframes
html2canvas cannot read a cross-origin iframe’s contentDocument. A sandboxed iframe without allow-same-origin has a similar restriction. You can capture the iframe only when it is same-origin and accessible, or ask the framed application to produce its own image.
Element dimensions and overflow
html2canvas uses the node’s layout. A node with overflow: auto normally contributes its visible box, not every item hidden beyond the scrollport. Temporarily change styles or capture a wrapper whose dimensions include the content if you need a complete chart or table.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →const originalOverflow = node.style.overflow;
node.style.overflow = 'visible';
try {
const canvas = await html2canvas(node);
// use canvas
} finally {
node.style.overflow = originalOverflow;
}
Capture the rendered node with Playwright
Playwright drives a real browser, so it is the better route for server-side JavaScript, end-to-end tests, and pixel output that reflects browser painting. Install it and its browser binaries:
npm install -D playwright
npx playwright install chromium
This Node.js script opens a page, waits for a locator, and writes the selected element to card.png:
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com/dashboard', { waitUntil: 'networkidle' });
const card = page.locator('.sales-card');
await card.waitFor({ state: 'visible' });
await card.screenshot({ path: 'card.png', type: 'png' });
await browser.close();
The documented locator behavior performs actionability checks, scrolls the element into view, captures a clip corresponding to that element, and returns image bytes if you omit path:
const imageBytes = await page.locator('#invoice-card').screenshot({
type: 'png',
animations: 'disabled'
});
await import('node:fs/promises').then(({ writeFile }) =>
writeFile('invoice-card.png', imageBytes));
Playwright details that affect the result
- If another element covers the locator, the screenshot contains the covering pixels; Playwright does not make an overlay disappear.
- A scrollable container contributes the content currently visible in that container. Scroll it deliberately before capture when a particular section is required.
- Wait for application state, not just a fixed delay. Prefer a locator assertion or a selector that indicates the chart or data has rendered.
- Use
deviceScaleFactoron the browser context when you need a higher-resolution artifact.
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
deviceScaleFactor: 2,
colorScheme: 'light'
});
Use Chrome DevTools Protocol for a clipped capture
CDP’s Page.captureScreenshot command accepts PNG, JPEG, or WebP and an optional clip rectangle. The response contains base64-encoded image data. This is useful when you already maintain a Chromium debugging connection and need protocol-level control.
import { chromium } from 'playwright';
import { writeFile } from 'node:fs/promises';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1200, height: 800 } });
await page.goto('https://example.com');
const box = await page.locator('.hero-card').boundingBox();
if (!box) throw new Error('The node is not visible');
const client = await page.context().newCDPSession(page);
const result = await client.send('Page.captureScreenshot', {
format: 'png',
clip: { x: box.x, y: box.y, width: box.width, height: box.height, scale: 1 }
});
await writeFile('hero-card.png', Buffer.from(result.data, 'base64'));
await browser.close();
Coordinates are viewport coordinates at capture time. If the page moves, animations run, or the device scale changes between measuring and capturing, the clip can be offset; freeze animations and measure immediately before the protocol call.
Common failures and fixes
“html2canvas is not defined”
The library was not loaded, the module import failed, or code ran before the script tag. Confirm the import, bundler configuration, and script order.
“document is not defined” in Node.js
That is expected: html2canvas requires browser globals and is not a Node.js renderer. Run it in a page, or switch to Playwright or Puppeteer on the server.
Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Images are missing
Check the browser console for CORS errors. Host images on the same origin, configure CORS, use a permitted proxy, or capture with a real browser process that can access the page.
The output looks different from the page
Use Playwright for actual browser pixels. With html2canvas, simplify unsupported effects, wait for fonts and images, and test the exact browsers your users run.
The selected node is missing in Playwright
Verify the locator, wait for it to become visible, and ensure it remains attached. If a framework replaces the node during rendering, locate it again immediately before screenshot().
The capture is blank or covered
Remove or hide consent banners, chat widgets, loading masks, and other overlays before capture, or wait until they disappear. For an iframe, verify that its origin permits access; browser security cannot be bypassed from page JavaScript.
Performance, reliability, and privacy
- Client memory: large, high-scale canvases consume substantial memory. Capture at the smallest useful scale and release object URLs after downloads.
- Server cost: launching a browser per request is slow. Reuse a controlled browser process, create isolated contexts, and close pages after each job.
- Determinism: disable animations, fix viewport and timezone, wait for stable data, and use the same browser version in visual tests.
- Secrets: do not expose private API tokens or authenticated page data in a client-side screenshot endpoint. Redact sensitive nodes before exporting.
- Freshness: Playwright options and CDP fields can change. Check the documentation for the version installed in your project before relying on a particular option.
Or skip the browser setup
ScreenshotNeo is a website screenshot API with element capture by CSS selector, so one request can replace your browser orchestration when you need a hosted result. It removes cookie and consent banners, newsletter popups, and chat widgets before the capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Use the ScreenshotNeo documentation for all options. This call captures an element on Stripe’s page (replace the selector and URL for your case):
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://stripe.com
--data-urlencode selector=.pricing-card
-o shot.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://stripe.com",
"selector": ".pricing-card",
},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com',
selector: '.pricing-card'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', buffer));
ScreenshotNeo includes 1,000 screenshots per month free 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 get an API key.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
FAQ
Can JavaScript take a screenshot of any DOM element?
It can capture an accessible same-page element with html2canvas or a browser-rendered element with Playwright, but cross-origin iframe contents and unreadable cross-origin assets remain restricted.
Which method is best for visual regression tests?
Use Playwright’s locator screenshot so the artifact comes from the browser’s rendered output. Fix the viewport, browser version, fonts, data, and animation state to reduce noise.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Can I capture an element without saving a file?
Yes. html2canvas can return a canvas or Blob, Playwright returns a byte buffer when no path is supplied, and CDP returns base64 image data.
Frequently Asked Questions
Does html2canvas capture video frames and browser UI?
No. It operates on page DOM and styles; browser chrome, permission prompts, and other UI outside the document are not part of the result.
Why does a scrollable element show only part of a long table?
Element screenshots represent the visible region of a scroll container. Scroll to the required position or temporarily resize a wrapper before capturing.
Is a server-side html2canvas endpoint possible without a browser?
Not with html2canvas alone. Its FAQ requires window and document, so use browser automation such as Playwright or Puppeteer for Node.js rendering.
Free tools Windows power users keep installed
One-click scans. No signup required.
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.

