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

There is no single JavaScript “screenshot” API for every job. First choose what you need: reconstruct an app-controlled element from its DOM, ask a user to select a tab/window/screen, or render a URL on a server. Use html2canvas for the first case, navigator.mediaDevices.getDisplayMedia() for user-approved display capture, and Puppeteer or Playwright on a server for repeatable URL screenshots. These approaches are not interchangeable: they differ in fidelity, permissions, browser support, and deployment.

Choose the capture model before writing code

Need Starting point Main trade-off
Capture an element or region your page controls DOM reconstruction with html2canvas It redraws from DOM information rather than copying browser pixels; unsupported CSS and cross-origin content can be missing or different.
Let a person choose a tab, window, or monitor getDisplayMedia() A permission prompt and picker are mandatory; secure-context, browser-support, and Permissions Policy restrictions apply.
Capture remote URLs or run a repeatable job Server-side Puppeteer or Playwright You must operate a server-side browser and account for its CPU, memory, navigation failures, and isolation.

Decide whether the output is a PNG, JPEG, or another format, whether the user must approve what is captured, and whether the page contains third-party frames or images. Those answers determine the implementation below.

Method 1: render an element with html2canvas

html2canvas traverses the document and builds a canvas from the DOM and styles. It does not take a literal screenshot of the browser’s rendered pixels. CSS that the library cannot reproduce, browser-native UI, plugins, and inaccessible cross-origin content can produce a mismatch. Read the html2canvas documentation for the supported rendering model.

Install and mark the capture target

Install the package in a build-based project:

npm install html2canvas

Give the region a stable selector. Keep transient controls outside it if they should not appear in the image.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
  • Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
  • Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
  • Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
  • Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
  • Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)
<section id="invoice" class="card">
  <h1>Invoice #1042</h1>
  <p>Due 30 September 2026</p>
  <button id="save-shot" type="button">Save image</button>
</section>
<div id="status" role="status" aria-live="polite"></div>

Complete browser code

import html2canvas from 'html2canvas';

const target = document.querySelector('#invoice');
const button = document.querySelector('#save-shot');
const status = document.querySelector('#status');

button.addEventListener('click', async () => {
  if (!target) return;
  button.disabled = true;
  status.textContent = 'Rendering…';

  try {
    const canvas = await html2canvas(target, {
      backgroundColor: '#ffffff',
      scale: Math.min(window.devicePixelRatio || 1, 2),
      useCORS: true,
      imageTimeout: 15000,
      logging: false
    });

    canvas.toBlob((blob) => {
      if (!blob) throw new Error('The browser could not encode the image.');
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = 'invoice-1042.png';
      link.click();
      URL.revokeObjectURL(url);
      status.textContent = 'Image saved.';
    }, 'image/png');
  } catch (error) {
    console.error(error);
    status.textContent = 'Could not render this region. Check image CORS and browser console errors.';
  } finally {
    button.disabled = false;
  }
});

scale controls output resolution and memory use. A higher value produces a sharper image but can exceed canvas limits on large regions. Use backgroundColor: null for transparency when the browser and target content permit it. You can pass a different element, use onclone to modify the temporary document, and set width, height, x, or y when you need a precise crop; consult the library documentation for the current option names.

Cross-origin images and iframes

Every image drawn into a canvas must satisfy browser origin rules. The image server needs an appropriate CORS response, and useCORS: true only asks the browser to make a CORS request—it cannot grant permission that the server did not provide. A same-origin proxy can fetch eligible assets and serve them from your origin. A cross-origin iframe’s DOM cannot be read by your page, so html2canvas cannot simply include its contents. The html2canvas FAQ explains proxy and tainted-canvas behavior.

When this method is a good fit

  • The application owns the markup and can accept a rendered approximation.
  • You need an in-browser download without sending page data to a server.
  • All important images are same-origin or configured for CORS.

Method 2: let a user capture a tab, window, or screen

The Screen Capture API returns a MediaStream after the user chooses a surface in a browser-controlled picker. It cannot silently select a monitor or capture pixels without consent. getDisplayMedia() requires a secure context (normally HTTPS), has limited availability, and can be blocked by Permissions Policy. See MDN’s getDisplayMedia reference, the Screen Capture API guide, and the display-capture policy reference.

Capture one frame from the selected surface

<button id="capture-screen" type="button">Choose a surface</button>
<img id="screen-preview" alt="Captured frame" hidden>
<div id="screen-status" role="status" aria-live="polite"></div>
<script type="module">
const button = document.querySelector('#capture-screen');
const preview = document.querySelector('#screen-preview');
const status = document.querySelector('#screen-status');

button.addEventListener('click', async () => {
  if (!navigator.mediaDevices?.getDisplayMedia) {
    status.textContent = 'Display capture is not available in this browser.';
    return;
  }

  let stream;
  try {
    status.textContent = 'Choose a tab, window, or screen in the browser picker.';
    stream = await navigator.mediaDevices.getDisplayMedia({
      video: { frameRate: { ideal: 5, max: 15 } },
      audio: false
    });

    const video = document.createElement('video');
    video.srcObject = stream;
    video.muted = true;
    await video.play();
    await new Promise(requestAnimationFrame);

    const canvas = document.createElement('canvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    canvas.getContext('2d').drawImage(video, 0, 0);
    preview.src = canvas.toDataURL('image/png');
    preview.hidden = false;
    status.textContent = 'Frame captured.';
  } catch (error) {
    if (error.name === 'NotAllowedError' || error.name === 'AbortError') {
      status.textContent = 'Capture was cancelled or denied.';
    } else {
      console.error(error);
      status.textContent = 'The selected surface could not be captured.';
    }
  } finally {
    stream?.getTracks().forEach(track => track.stop());
  }
});
</script>

Start the call from a clear click or keyboard action. Explain what the picker can expose and provide a visible cancel path. Stop every track immediately after the still is taken; leaving a track running can keep the browser’s capture indicator active. Chrome documents privacy controls for the surfaces shown in its picker at Chrome for Developers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Logitech G305 Lightspeed Wireless Gaming Mouse - Black
  • The next-generation optical HERO sensor delivers incredible performance and up to 10x the power efficiency over previous generations, with 400 IPS precision and up to 12,000 DPI sensitivity
  • Ultra-fast LIGHTSPEED wireless technology gives you a lag-free gaming experience, delivering incredible responsiveness and reliability with 1 ms report rate for competition-level performance
  • G305 wireless mouse boasts an incredible 250 hours of continuous gameplay on just 1 AA battery; switch to Endurance mode via Logitech G HUB software and extend battery life up to 9 months
  • Wireless does not have to mean heavy, G305 lightweight mouse provides high maneuverability coming in at only 3.4 oz thanks to efficient lightweight mechanical design and ultra-efficient battery usage
  • The durable, compact design with built-in nano receiver storage makes G305 not just a great portable desktop mouse, but also a great laptop travel companion, use with a gaming laptop and play anywhere

Permissions Policy and embedding

If your page is inside an iframe, the embedding response may need to allow the feature, for example Permissions-Policy: display-capture=(self "https://app.example"). A restrictive policy produces a failure even when the browser otherwise supports the API. You still cannot bypass the user’s picker or force a particular source.

Method 3: generate screenshots on a server

For scheduled captures, protected environments, or arbitrary public URLs, run a real browser with Puppeteer or Playwright on a server. html2canvas is client-side and depends on browser globals; its FAQ specifically points to these automation tools for server-side work. The basic workflow is:

  1. Accept and validate a URL or an allow-listed job.
  2. Launch or reuse an isolated browser, create a fresh context, and set viewport, locale, and authentication deliberately.
  3. Navigate with a timeout, wait for the page state or selector your job requires, then call the tool’s screenshot method.
  4. Return or store the bytes, close the page, and enforce limits on concurrency, navigation, and output size.

Do not expose an unrestricted “screenshot any URL” endpoint: attackers can use it to probe internal services. Restrict schemes to HTTPS/HTTP as appropriate, block private network ranges, cap redirects, and isolate browser processes. Treat cookies, authorization headers, and captured images as sensitive data.

Reliability, performance, and output decisions

Wait for the content you actually need

Fonts, lazy images, charts, and client-side data may arrive after the initial load. In a browser, wait for a known selector or an application-ready event rather than an arbitrary long delay. On a server, combine navigation timeouts with a specific readiness condition and fail clearly when it is not met.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Logitech M185 Compact Ambidextrous Wireless Mouse with Rubber Grips - Blue
  • Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
  • Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
  • Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
  • Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
  • Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)

Control memory and image size

Canvas memory grows with width × height × pixel scale. Capture only the required element, cap user-supplied dimensions, and lower scale for very large pages. Prefer JPEG for photographic output when some loss is acceptable; PNG is better for text and transparency. Revoke object URLs and stop media tracks after use.

Make failures observable

Log the URL (without secrets), elapsed stages, browser error, HTTP status where available, and final byte size. Return a useful client error for invalid input and a retryable status for temporary navigation failures. Never log authorization headers or raw page contents.

Troubleshooting common failures

The image is blank or missing styles

For html2canvas, confirm the target is visible, fonts have loaded, and unsupported CSS is not essential to the result. Capture after the framework has rendered. For server automation, wait for a deterministic ready selector and verify that the browser has network access to the asset host.

External images make the canvas unusable

Configure CORS on the image origin and keep useCORS enabled. If you cannot change that server, a controlled same-origin proxy may help; browser JavaScript cannot override the same-origin policy, and cross-origin iframe DOM remains inaccessible.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
  • Computer mouse for easily navigating a computer interface; click, scroll, and more
  • USB-A wired connection; if existing device only supports USB-C, an additional adapter will be required
  • High-definition (1000 dpi) optical tracking ensures responsive cursor control for precise tracking and easy text selection
  • 3 buttons offer effortless fingertip control
  • Plug-and-go ready for instant use

“Permission denied” from display capture

Serve the page over HTTPS, call the method directly from a user gesture, check that the browser supports it, and inspect the response’s Permissions Policy. The user may have cancelled the picker; handle NotAllowedError and AbortError without treating them as server faults.

The capture stops unexpectedly

A user can stop sharing from the browser’s indicator. Listen for ended on the video track if you build a longer-lived preview, disable controls when it fires, and release all tracks when the feature ends.

Server jobs time out or exhaust memory

Use bounded concurrency, per-navigation and total-job timeouts, a fresh context for untrusted pages, and a maximum output dimension. Reuse a browser process only with strict context cleanup; restart it when crashes or memory growth cross your operational threshold.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a hosted screenshot API and MCP server. A single GET request renders a URL and returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup 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.

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.

Use the complete API details and option names in the ScreenshotNeo documentation.

Best Value
Acer Wireless Mouse for Laptop, 2.4GHz Computer Mouse 3 Adjustable 1600 DPI
  • 【Plug and Play for Home/Office/School】The wireless computer mouse features 2.4GHz connectivity, delivering a stable, interference-free connection up to 32ft. Designed for 𝐦𝐞𝐝𝐢𝐮𝐦 𝐭𝐨 𝐥𝐚𝐫𝐠𝐞 𝐬𝐢𝐳𝐞𝐝 𝐡𝐚𝐧𝐝𝐬, it ensures comfortable use all day. Simply plug in the USB-A receiver for instant pairing—no drivers needed. 📌📌 If the mouse isn’t suitable, place the USB receiver in the battery compartment and return both.
  • 【3 Levels Adjustable DPI】This travel USB mouse offers 3 adjustable DPI settings (800, 1200, 1600), allowing you to customize sensitivity for precise design work. Effortlessly switch to match your task and elevate your productivity. 📌 Please remove the film at the bottom of the mouse before use.
  • 【Effortless Browsing】Equipped with forward and backward buttons, this computer mice streamlines your workflow, making it easy to navigate through web pages and files with a simple click. 📌Side button does not work on Mac.
  • 【Visible Indicator Light】 The pc mouse features a visual indicator for DPI levels and low battery alerts. The red light flashes once for 800 DPI, twice for 1200 DPI, and three times for 1600 DPI. When the battery level is below 10%, the light flashes red until the mouse is completely out of power.
  • 【Click to Wake】With smart sleep mode, it saves power by standby after 10 inactive minutes, just 2-3 clicks to wake. This efficient design delivers 3x longer battery life than motion-wake mice. Engineered for durability, its buttons and scroll wheel are tested for 10 million clicks, ensuring long-term reliability and consistent performance.

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 data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));

Beyond the basic URL, ScreenshotNeo supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or a custom viewport, retina scale, PDF paper and page controls, HTML/CSS-to-image, custom JavaScript and CSS, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, ad and tracker blocking, custom headers/cookies/user agent/Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Plans and billing

Plan Included shots Price
Free 1,000/month $0, no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Every feature is included on every plan, and yearly billing gives two months free. If you want cookie banners, popups, and chat widgets removed before the shot; no charge for bot checks, blank pages, or failed loads; AI-agent capture through MCP; and 1,000 free screenshots each month without a card, create a free ScreenshotNeo account.

Frequently Asked Questions

Can JavaScript take a screenshot of the current page?

Yes, but the technique determines what “screenshot” means. html2canvas reconstructs selected DOM content; it does not copy browser pixels. A true display capture requires the user-mediated Screen Capture API, while remote or scheduled pages require server-side browser automation.

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

Why can’t a web page capture another site’s iframe?

The browser’s same-origin policy prevents your page from reading a cross-origin frame’s DOM. You need cooperation from the other origin or a server-side capture of that page.

Can display capture run without showing a picker?

No. The browser requires a user permission flow and surface selection. Your code can explain the choices and stop the stream, but it cannot silently choose a tab, window, or screen.

Which approach is best for a marketing-site thumbnail service?

Use server-side browser automation or a screenshot API. A client-side library depends on the visitor’s browser and cannot reliably capture arbitrary remote URLs.

Quick Recap

SaleBestseller No. 1
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
Product carbon footprint: 3.97 kg CO2e; Contoured shape: Gives you more comfort and control
$14.90
SaleBestseller No. 3
Bestseller No. 4
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
Computer mouse for easily navigating a computer interface; click, scroll, and more; 3 buttons offer effortless fingertip control
$9.70

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.

Free tools Windows power users keep installed

One-click scans. No signup required.

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