Puppeteer screenshot with JavaScript disabled
Disable JavaScript before navigation, then capture a viewport, full page, or selected element with Puppeteer. Learn the options, pitfalls, and a ready-to-run example.
To take a Puppeteer screenshot with JavaScript disabled, call page.setJavaScriptEnabled(false) before navigating to the page, then capture it with page.screenshot(). The setting takes effect on the next navigation; it does not undo scripts that already ran.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setJavaScriptEnabled(false);
await page.goto('https://example.com', { waitUntil: 'load' });
await page.screenshot({ path: 'screenshot.png' });
} finally {
await browser.close();
}
This is useful for checking server-rendered or static output, seeing what a page exposes without client-side scripts, or producing a screenshot under a no-JavaScript rendering condition. It can also leave out content that the site normally creates with JavaScript.
1. Disable JavaScript before navigating
Set the page preference before the navigation whose result you plan to capture. If you disable JavaScript after page.goto(), scripts that already executed are not reversed. Puppeteer documents that the change takes full effect on the next navigation. See the Page.setJavaScriptEnabled() API reference.
You can check the current state with page.isJavaScriptEnabled(). This is a setting for the page, so set it on each new page where you need the same behavior.
const page = await browser.newPage();
await page.setJavaScriptEnabled(false);
console.log(await page.isJavaScriptEnabled()); // false
await page.goto('https://example.com');
2. Choose when navigation is ready
The example uses waitUntil: 'load', which waits for the page load event. You can also use Puppeteer navigation lifecycle options such as 'domcontentloaded', 'networkidle0', and 'networkidle2'. Choose based on the page and resources you need; a site with ongoing requests may not reach a network-idle condition promptly. Puppeteer’s screenshots guide uses networkidle2 in its example, but that does not make it the right wait condition for every site.
await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
timeout: 30000
});
A navigation wait only covers the selected browser lifecycle condition. It does not guarantee every image or resource has rendered correctly. When the page uses deferred images or styles, inspect the output and choose a suitable readiness condition for that target.
3. Capture the viewport, full page, or an element
By default, page.screenshot() captures the visible viewport. Set fullPage: true to capture the full document. To capture a specific element, locate it and call ElementHandle.screenshot(); this is useful for a chart, card, or other page region. The official guide covers both page and element screenshots.
// Viewport
await page.screenshot({ path: 'viewport.png' });
// Full document
await page.screenshot({ path: 'full-page.png', fullPage: true });
// One element
const card = await page.$('.pricing-card');
if (!card) throw new Error('Could not find .pricing-card');
await card.screenshot({ path: 'pricing-card.png' });
For a fixed rectangular crop, use the clip option with coordinates and dimensions. Make sure the clip rectangle fits the rendered page area you want.
await page.screenshot({
path: 'region.png',
clip: { x: 40, y: 80, width: 640, height: 400 }
});
4. Select format and output handling
Puppeteer returns screenshot bytes as a Uint8Array by default. Set path to save directly to a file. The file extension determines the image type if you do not set type; the documented default type is PNG. Supported screenshot options also include transparency and lossy-image quality settings.
| Need | Option | Notes |
|---|---|---|
| Save to disk | path: 'screenshot.png' |
The extension is used to infer the format when type is omitted. |
| Return bytes | Omit path |
The result is a Uint8Array; pass it to a file writer or another API. |
| Return base64 | encoding: 'base64' |
Returns a base64 string rather than bytes. |
| Choose image format | type: 'png', 'jpeg', or 'webp' |
PNG is the documented default. Use a supported lossy format when you need its quality option. |
| Transparent background | omitBackground: true |
Removes the default white page background where transparency is supported. |
| Lossy quality | quality: 80 |
Applies to supported lossy formats, not PNG. |
const imageBytes = await page.screenshot({
type: 'jpeg',
quality: 80,
fullPage: true
});
// imageBytes is a Uint8Array.
Consult Puppeteer’s ScreenshotOptions reference for the current option types and constraints.
5. Understand what the screenshot shows
With JavaScript disabled, the result depends on the HTML, stylesheets, images, fonts, and other resources the browser loads. A page that builds its main content in client-side scripts may show less content or fewer interactions than usual. That is an expected consequence of disabling page scripts, but the precise appearance depends on how the target site is built.
JavaScript being off does not mean the browser stops loading CSS or images. Check the actual screenshot if fidelity matters, especially if the target relies on scripts to reveal content, set dimensions, or trigger rendering behavior.
6. Complete runnable examples
JavaScript with Puppeteer
Save this as screenshot.mjs, install Puppeteer with npm install puppeteer, and run node screenshot.mjs. It saves both a viewport and full-page capture while ensuring the browser closes if navigation or capture fails.
import puppeteer from 'puppeteer';
const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setJavaScriptEnabled(false);
await page.setViewport({ width: 1440, height: 900 });
await page.goto(url, { waitUntil: 'load', timeout: 30000 });
await page.screenshot({ path: 'viewport.png', type: 'png' });
await page.screenshot({ path: 'full-page.png', type: 'png', fullPage: true });
} finally {
await browser.close();
}
cURL
cURL does not run Puppeteer or control a browser’s JavaScript setting, so it cannot reproduce this browser workflow on its own. It can fetch HTML for inspection, but that is not a rendered screenshot. To request a screenshot through a service that handles the browser capture, use the ScreenshotNeo example below.
Python
Python’s standard HTTP clients do not provide Puppeteer’s page setting or browser screenshot method. For a Python program that needs this browser behavior, use a browser automation library and its own JavaScript-disable control; the following Python example instead calls ScreenshotNeo’s screenshot API.
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as f:
f.write(r.content)
Node.js API request
This Node.js example makes a screenshot API request, rather than launching Puppeteer locally. See the ScreenshotNeo API documentation for request options.
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
7. Or skip the browser setup
ScreenshotNeo takes screenshots through one API call. It does not expose a documented option in the supplied product facts to disable JavaScript, so use Puppeteer above when that specific browser setting is required. For ordinary screenshot capture, the call is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo documentation for the API options. ScreenshotNeo accepts cookie and 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, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Sign up for ScreenshotNeo and get 1,000 free screenshots a month, with no card.
8. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| JavaScript content still appears | The scripts ran before JavaScript was disabled, or the page was not navigated again after changing the setting. | Call setJavaScriptEnabled(false) before goto() for the capture navigation. |
| Expected content is missing | The site creates that content with client-side JavaScript. | This is expected in a no-JavaScript capture. If the content must be present, capture with JavaScript enabled or use a server-rendered/static version. |
| Screenshot is blank or incomplete | Navigation may have reached the chosen lifecycle point before the page’s required resources or rendering were ready, or the site may not serve useful content without scripts. | Inspect the page output, try a different navigation wait condition, and confirm the URL loads successfully in the browser. |
| Navigation hangs or times out | The site may keep requests open, making a network-idle condition unsuitable, or the page may be slow/unreachable. | Try load or domcontentloaded, set an explicit timeout, and handle navigation errors. Do not assume every page reaches network idle. |
| Element screenshot throws or selector is missing | The selector does not match an element in the no-JavaScript DOM. | Check the selector and confirm the element exists without scripts before taking the element screenshot. |
| Quality option has no effect | Quality applies to supported lossy formats, not PNG. | Choose a supported lossy type such as JPEG, then set quality. |
| Output file type is unexpected | The file extension and explicit type do not match, or no type was specified and the extension was used. |
Set a supported type explicitly or use a matching path extension. |
9. Performance, reliability, and cost
Local Puppeteer captures require a running browser process and the page’s resources to load. Full-page screenshots and image output can require more memory and disk space than a viewport capture; choose the smallest capture scope and format that meets the need. Close the browser in a finally block so an error does not leave the browser process running.
Reliability depends on navigation success and the target site’s response. Use an explicit timeout, catch navigation and screenshot errors in production code, and decide how to handle pages whose content depends on JavaScript. The research sources provide no benchmark or fixed cost figure for running Puppeteer, so infrastructure cost depends on where and how often the script runs.
For hosted captures, ScreenshotNeo’s stated billing behavior is that only clean shots are billed; bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. The plans are Free: 1,000 per month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Yearly billing gives two months free. See ScreenshotNeo for product details.
10. FAQ
Does disabling JavaScript block CSS and images?
No. The setting disables page JavaScript. The browser can still load stylesheets, images, and other resources the page serves.
Can I disable JavaScript after opening the page?
You can change the setting, but it takes full effect on the next navigation and does not undo scripts that already ran. Navigate again after setting it to false.
Does fullPage: true change the JavaScript setting?
No. It changes the capture area from the viewport to the full page. Disable JavaScript separately before navigation.
Can ScreenshotNeo take a screenshot with JavaScript disabled?
The supplied ScreenshotNeo options do not include a JavaScript-disable setting. Use Puppeteer when disabling scripts is a requirement; use ScreenshotNeo for its API and other listed capture features.


