Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use a Chrome profile preference in Selenium; headless mode alone does not disable JavaScript. The practical configuration is profile.default_content_setting_values.javascript: 2 together with Chrome’s --headless argument. Because ChromeDriver’s official capability documentation does not promise that exact preference key across versions, verify the result with a page whose visible output depends on a script and with the Chrome and driver versions installed on your machine.
Minimal working example
Install Selenium and ensure a compatible ChromeDriver is available (Selenium Manager can locate a driver in many current Selenium setups):
python -m pip install -U selenium
Then create a headless Chrome session with JavaScript disabled:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_experimental_option(
"prefs",
{"profile.default_content_setting_values.javascript": 2},
)
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com")
print(driver.title)
print(driver.page_source[:500])
finally:
driver.quit()
The value 2 is the commonly used Chrome content-setting value for blocking JavaScript. Treat it as a practical, version-sensitive setting rather than a permanently guaranteed ChromeDriver API. If the page needs JavaScript to create its content, the returned DOM may be sparse, an interaction may do nothing, or navigation may reveal an error page instead of the application.
#1 Best Overall
- FOR HOME, WORK, & SCHOOL – With an Intel processor, 14-inch display, custom-tuned stereo speakers, and long battery life, this Chromebook laptop lets you knock out any assignment or binge-watch your favorite shows.
- HD DISPLAY, PORTABLE DESIGN – See every bit of detail on this micro-edge, anti-glare, 14-inch HD (1366 x 768) display (1); easily take this thin and lightweight laptop PC from room to room, on trips, or in a backpack.
- ALL-DAY PERFORMANCE – Reliably tackle all your assignments at once with the quad-core, Intel Celeron N4120—the perfect processor for performance, power consumption, and value (2).
- 4K READY – Smoothly stream 4K content and play your favorite next-gen games with Intel UHD Graphics 600 (3) (4).
- MEMORY AND STORAGE – Enjoy a boost to your system’s performance with 4 GB of RAM while saving more of your favorite memories with 64 GB of reliable flash-based eMMC storage (5).
What headless mode does (and does not do)
--headless removes the visible browser window; it does not switch off script execution. Current Chrome documentation describes a unified headless implementation selected with --headless. The older separate implementation is available as the standalone chrome-headless-shell beginning with Chrome 132.0.6793.0. Selenium’s historical --headless=new examples came from the transition period; for a current configuration, start with --headless and only change it if your installed Chrome documentation requires something different.
JavaScript blocking is a separate profile setting passed to ChromeDriver through add_experimental_option("prefs", ...). ChromeDriver normally creates a temporary profile for each session, so this preference applies to that isolated run and does not alter your everyday Chrome profile.
Verify that scripts are really blocked
A page that happens not to use JavaScript cannot prove that the setting worked. Use a deliberately controlled test page whose script changes a visible element:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_experimental_option(
"prefs",
{"profile.default_content_setting_values.javascript": 2},
)
driver = webdriver.Chrome(options=options)
try:
driver.get("data:text/html,<div id='status'>before</div><script>document.getElementById('status').textContent='after'</script>")
status = driver.find_element("id", "status").text
print(status) # expected: before
print("after" in driver.page_source) # expected: False
finally:
driver.quit()
If the element still says “before,” the script-driven change did not occur in this test. That is a behavioral check for this session, not proof that every execution context, extension, or browser version is blocked. A second useful check is to reload a real page and compare its script-dependent and non-script content; Chrome’s own troubleshooting guidance uses reload behavior to reveal whether a site depends on JavaScript.
Use an isolated temporary profile or a persistent one
The default temporary profile is usually the safest choice for automation. It avoids cookies, cached permissions, extensions, and content settings left by another run.
| Profile choice | Persistence | Isolation | Parallel-session guidance |
|---|---|---|---|
| ChromeDriver temporary profile | Removed after the session | High; starts with clean state | Best default; separate sessions do not share a profile directory |
Dedicated user-data-dir |
Retained between runs | Depends on what that profile already contains | Use a different directory for every concurrent session |
To retain settings, point Chrome at a directory dedicated to automation:
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
profile = Path("selenium-js-off")
profile.mkdir(exist_ok=True)
options = Options()
options.add_argument("--headless")
options.add_argument(f"--user-data-dir={profile.resolve()}")
options.add_experimental_option(
"prefs",
{"profile.default_content_setting_values.javascript": 2},
)
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com")
finally:
driver.quit()
Never point simultaneous ChromeDriver processes at the same profile directory. Chrome may lock it or allow one run to change state underneath another. A persistent profile can also contain permissions that make results differ from a clean run, so use the temporary profile when reproducing a failure.
Make the configuration more predictable
Pin the browser and driver relationship
Keep Chrome and ChromeDriver compatible and record their versions in CI logs. The preference key is not enumerated as a stable contract in the ChromeDriver capability documentation reviewed for this configuration, so a browser upgrade is a reason to rerun the controlled verification page.
Load the page, then inspect what actually arrived
Do not use a long explicit wait for a script-generated selector when JavaScript is intentionally disabled; that selector may never appear. Instead, wait for a server-rendered element, inspect driver.current_url, save driver.page_source, and capture the browser title or visible error text.
Keep state changes explicit
Cookies, local storage, extensions, and a custom profile can affect what a site serves even when JavaScript is blocked. For a reproducible test, start a fresh temporary profile, use a fixed URL, and avoid reusing a profile from an interactive Chrome session.
What breaks when JavaScript is disabled
- Single-page applications may return only a shell because content is fetched and rendered by script.
- Buttons, menus, form validation, infinite scrolling, and client-side redirects may stop responding.
- Authentication flows, challenge pages, consent dialogs, and payment widgets commonly require JavaScript.
- Some sites return different markup or an explanatory “enable JavaScript” page.
If your objective is to inspect server-rendered HTML, blocking scripts can be useful. If you need the final visual state of a modern application, disabling JavaScript defeats the code that creates that state; leave it enabled and control the page with waits, network blocking, or targeted DOM inspection instead.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
- TWEIGHT 2-in-1 DESIGN At just under 3 pounds, the Chromebook Plus is incredibly lightweight. You can easily fold it into tablet mode for comfortable viewing and browsing
- BUILT-IN PEN Experience the power of the incredibly precise built-in pen that never needs charging. It's always ready to write, sketch, edit, magnify and even take screenshots
- DUAL CAMERA Fold your laptop into tablet mode to capture clear shots and even zoom in for a closer look with the revolutionary 13MP world-facing camera with autofocus
- CHROME OS AND GOOGLE PLAY STORE Create, explore and browse on a bigger screen with the tools you use every day —all on the secure Chrome OS
- POWER AND PERFORMANCE Tackle anything with a long-lasting battery and Intel Celeron processor. Store more with 64GB of built-in memory and add up to 400GB with a microSD card.Bluetooth v4.0
Troubleshooting
Scripts still run
- Cause: the preference was misspelled, attached to a different options object, or not passed to the driver.
- Fix: print or review the exact options construction, use a fresh temporary profile, and rerun the controlled test page. Confirm that the session is the Chrome instance created by this script.
The page is blank or incomplete
- Cause: the site renders its content entirely in JavaScript.
- Fix: inspect the initial HTML and network-independent server response. If you need the application output, remove the blocking preference rather than adding longer waits.
SessionNotCreatedException or Chrome fails to start
- Cause: an incompatible Chrome/ChromeDriver pair, an invalid profile directory, or an environment that needs additional sandbox configuration.
- Fix: update Selenium and use a driver compatible with the installed Chrome; switch back to a temporary profile; ensure the profile path exists and is writable; then test a plain
webdriver.Chrome()session before adding other arguments.
A persistent profile is locked
- Cause: another Chrome or ChromeDriver process is using the same
user-data-dir. - Fix: close the other process or assign a unique profile directory per worker. Do not solve the problem by sharing one profile across parallel jobs.
The test says “before” even though the real site changes
- Cause: the test page was not actually loaded, or the assertion is reading a different element than the script changes.
- Fix: print
current_url, title, and a portion ofpage_source; use a simple data URL or a local fixture whose script and target element are unambiguous.
Performance, reliability, and cost considerations
Disabling JavaScript is a correctness choice, not a guaranteed speed optimization. It can avoid script work on pages that otherwise execute large bundles, but it can also produce redirects, retries, or incomplete documents that make downstream processing less reliable. Measure the behavior you need—DOM completeness, navigation success, and extraction accuracy—rather than assuming a faster wall-clock time.
For repeatable automation, log the Chrome version, ChromeDriver version, URL, profile mode, and whether the verification fixture passed. Treat a browser upgrade as a compatibility change and rerun the fixture. A temporary profile reduces contamination from prior permissions; a dedicated persistent profile is appropriate only when retaining cookies or other state is part of the test.
Or skip the browser setup
If the goal is a clean screenshot or PDF rather than browser-level JavaScript testing, ScreenshotNeo provides a single website screenshot API request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
One-call cURL example (see the ScreenshotNeo documentation for all options):
Free tools Windows power users keep installed
One-click scans. No signup required.
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)
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}`);
You can also request full-page captures with lazy images loaded, a CSS-selected element, dark mode, device presets, custom viewport and retina scale, PDFs with paper size/margins/orientation/page ranges, custom CSS or JavaScript, clicks, selector waits, delays or network-idle waits, blocked ads/trackers/requests/resource types, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification. Parameter names used by other screenshot APIs also work for easier migration.
Every feature is included on every plan: 1,000 shots per month free with no card, then Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing provides two months free. Create a free ScreenshotNeo account to start.
FAQ
Does setting JavaScript to 2 block every possible script?
It requests that Chrome block site JavaScript for the profile. Verify the actual session with a controlled fixture; the preference is not documented as a cross-version guarantee for every execution context.
Should I use --headless=new?
Use current Chrome’s --headless guidance. --headless=new belonged to the transition to unified headless mode and is not required for the current unified implementation.
Can I reuse my normal Chrome profile?
Use a dedicated profile directory if persistence is required. Reusing an everyday profile imports unknown state, and sharing one directory between concurrent sessions can cause locking and cross-test interference.
Frequently Asked Questions
Does setting JavaScript to 2 block every possible script?
It requests that Chrome block site JavaScript for the profile. Verify the actual session with a controlled fixture; the preference is not documented as a cross-version guarantee for every execution context.
Should I use –headless=new?
Use current Chrome’s –headless guidance. –headless=new belonged to the transition to unified headless mode and is not required for the current unified implementation.
Can I reuse my normal Chrome profile?
Use a dedicated profile directory if persistence is required. Reusing an everyday profile imports unknown state, and sharing one directory between concurrent sessions can cause locking and cross-test interference.
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.

