Free tools Windows power users keep installed
One-click scans. No signup required.
Use Playwright or Puppeteer when JavaScript runs in Node.js and you need a screenshot of the page as a browser actually renders it. Use html2canvas when code runs inside the page and you want an in-page export of an element or report. A browser automation library can capture the viewport, the entire scrollable document, or one element. html2canvas is easier to add to a button in an existing page, but it reconstructs pixels from the DOM and styles rather than taking a native browser screenshot.
This guide shows how to take a screenshot of an HTML page using JavaScript, how to capture a full page or one HTML element, and how to avoid the cross-origin and timing problems that make captures blank or incomplete.
Choose the JavaScript screenshot method
| Method | Where it runs | Best for | Rendering behavior |
|---|---|---|---|
| Playwright | Node.js or server-side automation | High-fidelity captures, visual tests, repeatable viewport settings | Drives a real browser |
| Puppeteer | Node.js or server-side automation | Chrome-oriented automation and page or element files | Drives a real browser |
| html2canvas | Browser code inside the page | An “Export this card” or report button | Rebuilds an image from DOM information and applied styles |
For an automated service, start with Playwright. For an existing web page where the user clicks a button, start with html2canvas. Puppeteer is a solid alternative when your automation stack already uses it.
Take a full-page screenshot with Playwright
Install Playwright in your Node.js project, then create a module such as screenshot.mjs. The browser opens at a known viewport, waits for navigation and network activity to settle, and writes a PNG containing content below the fold.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches#1 Best Overall
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', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'page.png', fullPage: true });
await browser.close();
fullPage: true is the important distinction from a viewport-only shot. Without it, the file represents only the visible 1440×900 area. The call also returns screenshot data if you omit path, which is useful when an API should return bytes, store an object, or pass the image to another function.
Capture one HTML element
Use a locator when the page contains a component such as an invoice, chart, or product card:
await page.locator('.invoice').screenshot({ path: 'invoice.png' });
The locator must resolve to the element you intend to export. If the selector is too broad, the resulting image may include an unexpected container; if it matches nothing, wait for the component or correct the selector before capturing.
Control the output
Playwright’s screenshot options include full-page capture, image format and quality controls, and element or locator screenshots. Use a fixed viewport for repeatable visual regression tests. Choose JPEG or WebP when file size matters; retain PNG when sharp text, transparency, or lossless output is important. If the application renders data after navigation, wait for the relevant selector or application state rather than assuming that the first loaded document is complete.
Take a full-page screenshot with Puppeteer
Puppeteer follows the same browser-driven model. Its documented pattern waits for the page to become quiet, captures the complete document, and closes the browser:
Rank #2
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'page.png', fullPage: true });
await browser.close();
networkidle2 waits until network activity is low, which is often safer for pages that load data and images after the initial response. It is not a guarantee that every animation or application task has finished, so add an explicit wait for a selector when the page has a known ready state.
Capture an element in Puppeteer
Find the element, then call its screenshot method. The exact handle or locator code depends on your Puppeteer version and selector strategy, but the principle is the same: resolve the component after it is rendered and capture that element instead of the whole document. Puppeteer’s Page.screenshot() can return image data (a base64 string or Uint8Array, depending on options) when you do not write directly to a path.
Take a screenshot in the browser with html2canvas
html2canvas is appropriate when the JavaScript is already running on the page. It reads the current DOM and applied styles and paints a canvas; it does not ask the browser for a native screenshot. This makes it convenient for a download button, while also explaining why the result can differ from what the browser displays.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →<script type="module">
import html2canvas from 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/+esm';
const element = document.querySelector('#capture');
const canvas = await html2canvas(element, { backgroundColor: '#fff' });
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
const link = document.createElement('a');
link.download = 'capture.png';
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
</script>
Replace #capture with the element to export. Pass the document’s root element if you want the page area represented by the DOM, but do not expect this to reproduce browser chrome or inaccessible content. The project warns that output may not be 100% accurate to the real browser representation and that html2canvas is not a Node.js renderer.
Make the button explicit
In production, trigger the code from a user action, check that element is not null, and handle a null blob before creating the download URL. Revoke the object URL after the download has been initiated so repeated exports do not accumulate browser resources.
Full page or one element?
- Use full-page capture when a reader needs the complete scrollable document, including sections below the fold. Set
fullPage: truein Playwright or Puppeteer. - Use element capture for a component such as
.invoice, a dashboard panel, or a report card. Element screenshots avoid unrelated navigation and page margins. - Use a viewport capture when you are testing exactly what a user sees at a specified width and height. Omit
fullPageand set the viewport deliberately.
For visual comparisons, keep viewport dimensions, device scale, fonts, locale, and data stable. A different font load or a late animation can produce a different image even when the code is unchanged.
Timing, lazy content, and dynamic pages
Navigation completion is not the same as visual readiness. A robust capture sequence is:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Open a browser context with the desired viewport.
- Navigate with an appropriate wait condition such as Playwright’s
networkidleor Puppeteer’snetworkidle2. - Wait for the selector that proves the application has rendered its data.
- Scroll or otherwise trigger lazy content if the page requires it.
- Disable or wait out animations when pixel stability matters.
- Capture the page or locator, then close the browser in a
finallypath so failures do not leak processes.
Network-idle waits can be unsuitable for pages with analytics, chat, or long-polling requests that never become quiet. In those cases, a specific ready selector or a bounded delay is more deterministic than waiting forever.
Cross-origin limitations and security
Images and fonts
html2canvas may be unable to use images or fonts fetched from another origin. The browser can taint the canvas, preventing export, unless the resource permits the required cross-origin access. Configure CORS on the asset host or serve the asset through a same-origin proxy that you control. A browser automation screenshot does not have this particular canvas restriction because it captures the rendered browser surface, although authentication and network access still need to be configured.
Cross-origin iframes
html2canvas cannot render a cross-origin iframe because browser security rules prevent access to its contentDocument. Capture the iframe’s page separately with browser automation, or arrange for the content to be available in the same origin when that is legally and technically appropriate.
Rank #4
Credentials and private pages
Do not place secrets in a client-side html2canvas script. For a private page, use a controlled server-side browser context with the required cookies or headers, and avoid writing sensitive screenshots to publicly readable paths.
Output formats, bytes, and storage
Playwright and Puppeteer can write PNG files or return image bytes. Returning bytes is preferable for an HTTP endpoint that streams the result or uploads it to object storage. PNG preserves crisp text and transparency; JPEG and WebP can reduce size when photographic content or bandwidth is more important. html2canvas produces a canvas, which you can convert with toBlob and then upload or download. The chosen format does not fix a rendering problem: capture only after the required content and fonts are present.
Troubleshooting checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| Only the top of the page appears | Viewport capture was requested | Set fullPage: true in Playwright or Puppeteer. |
| Blank or half-rendered image | Capture ran before data, fonts, or images settled | Wait for a ready selector, use a suitable network wait, and handle lazy content. |
| html2canvas throws a security or tainted-canvas error | Cross-origin image or font | Enable appropriate CORS or use a same-origin proxy. |
| An embedded frame is missing | The iframe is cross-origin | Capture that page separately with browser automation; html2canvas cannot read it. |
| Screenshot differs between runs | Variable viewport, fonts, data, or animation | Fix the viewport and environment, wait for fonts and a stable selector, and disable animations. |
| Node.js cannot use html2canvas | html2canvas is a browser DOM renderer | Use Playwright or Puppeteer for server-side work. |
| Browser process remains after an error | Close was skipped | Put browser cleanup in a finally block. |
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server, so a server can request a rendered image without managing Playwright or Puppeteer. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether it was billed.
One GET request returns PNG, JPEG, WebP, or PDF. The API supports full-page and CSS-selector element capture, device presets or custom viewports, dark mode, retina scale, lazy-image loading, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, TTL-based caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification. Its parameter names also match those used by other screenshot APIs, which can simplify migration.
See the ScreenshotNeo documentation for authentication and all options. A minimal cURL request is:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallcurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent 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)
Equivalent 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}`);
The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. An MCP server supplies take_screenshot, get_page_info, and capture_pdf tools to Claude, Cursor, and other MCP clients. Create a free ScreenshotNeo account to start.
Best Value
Which approach should you use?
- Choose Playwright for the most controlled, browser-faithful Node.js automation and visual regression work.
- Choose Puppeteer when its Chrome automation model fits your existing project.
- Choose html2canvas for a browser-only “download this element” feature when cross-origin content is under your control.
- Choose ScreenshotNeo when you want an API or MCP workflow without maintaining browser infrastructure, especially when consent UI, failed pages, or agent-driven capture matters.
Frequently Asked Questions
Can JavaScript take a screenshot without a browser?
Not with html2canvas: it needs the page DOM and runs in a browser. For server-side JavaScript, use a real-browser automation library such as Playwright or Puppeteer, or call a screenshot API.
How do I screenshot an HTML element instead of the whole page?
In Playwright, call page.locator('your-selector').screenshot(). With html2canvas, pass the element returned by document.querySelector().
Why is my full-page screenshot still missing content?
Full-page mode extends the capture area, but it does not make an application finish rendering. Wait for the page’s data and lazy content before calling the screenshot method.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Is html2canvas the same as a native browser screenshot?
No. It reconstructs an image from DOM information and styles, so unsupported CSS, cross-origin resources, and iframes can differ from the browser’s actual pixels.
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.

