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 →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Yes, you can run an ad-blocking extension in Selenium’s headless Chrome—but use Chrome’s new Headless mode and choose the browser build and extension format deliberately. Start with --headless=new. Load a packaged extension with Selenium’s add_extension(), or load an unpacked directory with --load-extension only when using Chromium or Chrome for Testing. Official Chrome-branded builds stopped accepting that flag starting in Chrome 137.
What works, and what changed
Chrome’s unified Headless mode, introduced in Chrome 112, runs without creating visible platform windows while retaining regular Chrome functionality. Chrome’s extension end-to-end testing guidance specifically recommends --headless=new and warns that the old Headless implementation cannot load extensions.
The old implementation was removed from the main Chrome binary in Chrome 132 and remains available as a separate chrome-headless-shell binary. Do not use that legacy shell for this workflow.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
There is a second, independent compatibility issue. Starting with Chrome 137, official Chrome-branded builds reject the --load-extension command-line switch. Chromium and Chrome for Testing continue to support it. Consequently, an older tutorial that launches google-chrome with an unpacked extension may fail after a browser update even though the Selenium code is otherwise valid.
#1 Best Overall
- KEYBOARD: The keyboard works for Windows with hot keys that enable easy access to Media, My Computer, Mute, Volume up/down, and Calculator
- EASY SETUP: Experience simple installation with the USB wired connection
- VERSATILE COMPATIBILITY: This keyboard is designed to work with multiple Windows versions, including Vista, 7, 8, 10 offering broad compatibility across devices.
- SLEEK DESIGN: The elegant black color of the wired keyboard complements your tech and decor, adding a stylish and cohesive look to any setup without sacrificing function.
- FULL-SIZED CONVENIENCE: The standard QWERTY layout of this keyboard set offers a familiar typing experience, ideal for both professional tasks and personal use.
Prerequisites and a deliberate setup
- Python 3 and Selenium 4 (the current Selenium Python API documents
ChromeOptions.add_extension()andadd_argument()). - A Chromium-based browser whose executable and version you can identify.
- An ad blocker supplied either as a packaged
.crxfile or as an unpacked extension directory. - A writable, unique user-data directory when runs must be isolated or parallel.
Pick the browser distribution first
| Browser build | Packaged .crx |
Unpacked directory |
|---|---|---|
| Official Chrome-branded build | Use Selenium’s add_extension(); verify the extension and browser policy in your environment. |
Not accepted through --load-extension from Chrome 137 onward. |
| Chromium | Use add_extension(). |
Supported with --load-extension=/absolute/path. |
| Chrome for Testing | Use add_extension(). |
Supported with --load-extension=/absolute/path. |
If your organization requires the official Chrome brand, obtain a CRX and use add_extension(). If you need to work from source or an unpacked build, select Chromium or Chrome for Testing and pin that browser in CI.
Option A: load a packaged CRX in new Headless mode
A CRX is the simplest route when the extension publisher provides one. The path must be readable by the process running the test.
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
EXTENSION = Path("/opt/extensions/ad-blocker.crx").resolve()
PROFILE = Path("/tmp/selenium-adblock-profile").resolve()
options = Options()
options.add_argument("--headless=new")
options.add_argument(f"--user-data-dir={PROFILE}")
options.add_argument("--window-size=1365,900")
options.add_extension(str(EXTENSION))
# Selenium Manager can locate a compatible driver, or configure a driver explicitly.
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com/")
print(driver.title)
print(driver.current_url)
finally:
driver.quit()
Use a fresh profile when you want deterministic behavior. Reusing a profile can preserve extension settings, cached filter lists, cookies, and permissions from an earlier run. A unique directory per worker also prevents profile-lock errors in parallel jobs.
CRX caveats
- Some managed environments allow only administrator-approved extensions.
- The extension may require its own first-run consent or filter-list update before blocking begins.
- A browser starting successfully does not prove that requests are being blocked. Assert behavior on a page you control or inspect network results with your test instrumentation.
Option B: load an unpacked extension with Chromium or Chrome for Testing
An unpacked directory must contain the extension’s manifest.json at its root. This method is appropriate for a checked-out extension or a test build. It is not a solution for official Chrome-branded binaries from Chrome 137 onward.
Rank #2
- Reliable Plug and Play: The USB receiver provides a reliable wireless connection up to 33 ft (1), so you can forget about drop-outs and delays and you can take it wherever you use your computer
- Type in Comfort: The design of this keyboard creates a comfortable typing experience thanks to the low-profile, quiet keys and standard layout with full-size F-keys, number pad, and arrow keys
- Durable and Resilient: This full-size wireless keyboard features a spill-resistant design (2), durable keys and sturdy tilt legs with adjustable height
- Long Battery Life: MK270 combo features a 36-month keyboard and 12-month mouse battery life (3), along with on/off switches allowing you to go months without the hassle of changing batteries
- Easy to Use: This wireless keyboard and mouse combo features 8 multimedia hotkeys for instant access to the Internet, email, play/pause, and volume so you can easily check out your favorite sites
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
EXTENSION_DIR = Path("/opt/extensions/ad-blocker-unpacked").resolve()
PROFILE = Path("/tmp/selenium-adblock-cft-profile").resolve()
options = Options()
options.binary_location = "/opt/chrome-for-testing/chrome" # Chromium or Chrome for Testing
options.add_argument("--headless=new")
options.add_argument(f"--load-extension={EXTENSION_DIR}")
options.add_argument(f"--user-data-dir={PROFILE}")
options.add_argument("--window-size=1365,900")
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com/")
print(driver.title)
finally:
driver.quit()
Use an absolute path and confirm the directory is readable. If this raises an “unknown switch” or similar startup error with branded Chrome, do not keep changing Selenium syntax: switch to a CRX with add_extension(), or run Chromium/Chrome for Testing.
A reusable Selenium helper
Keeping browser selection and extension selection explicit makes upgrades easier to diagnose.
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def start_chrome(*, crx=None, unpacked=None, binary=None, profile=None):
if crx and unpacked:
raise ValueError("Choose crx or unpacked, not both")
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1365,900")
if binary:
options.binary_location = str(Path(binary).resolve())
if profile:
options.add_argument(f"--user-data-dir={Path(profile).resolve()}")
if crx:
options.add_extension(str(Path(crx).resolve()))
elif unpacked:
options.add_argument(f"--load-extension={Path(unpacked).resolve()}")
else:
raise ValueError("Provide crx or unpacked")
return webdriver.Chrome(options=options)
# Packaged extension:
driver = start_chrome(crx="/opt/extensions/ad-blocker.crx", profile="/tmp/run-1")
try:
driver.get("https://example.com/")
finally:
driver.quit()
How to verify that blocking actually happened
Do not treat a clean-looking screenshot as proof. Ad blockers can remove visual elements, block network requests, or require filter-list initialization. Build a page or test fixture with a known ad URL, then verify the expected DOM or request outcome. Check the page after the extension has had time to initialize, and avoid brittle assertions tied to one third-party ad network.
Inspecting extension UI
Selenium cannot directly attach to an extension service worker. When you must inspect extension state, navigate to an extension page such as chrome-extension://<extension-id>/popup.html and execute JavaScript there. The extension ID must be discovered from the installed build or its published metadata, and the popup path varies by extension.
Rank #3
- All-day Comfort: The design of this standard keyboard creates a comfortable typing experience thanks to the deep-profile keys and full-size standard layout with F-keys and number pad
- Easy to Set-up and Use: Set-up couldn't be easier, you simply plug in this corded keyboard via USB on your desktop or laptop and start using right away without any software installation
- Compatibility: This full-size keyboard is compatible with Windows 7, 8, 10 or later, plus it's a reliable and durable partner for your desk at home, or at work
- Spill-proof: This durable keyboard features a spill-resistant design (1), anti-fade keys and sturdy tilt legs with adjustable height, meaning this keyboard is built to last
- Plastic parts in K120 include 51% certified post-consumer recycled plastic*
For ordinary integration tests, prefer user-facing assertions: an ad slot is absent, a known resource is unavailable, or page content remains usable. Internal service-worker details are more fragile across extension releases.
Waiting, timing, and deterministic captures
Wait for the page, not an arbitrary sleep
Use Selenium waits for a meaningful condition such as the main content selector. A fixed delay can be useful for an extension’s first initialization, but it should be a last resort and kept short.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, 30)
driver.get("https://example.com/")
wait.until(lambda d: d.execute_script("return document.readyState") == "complete")
wait.until(lambda d: d.find_element(By.TAG_NAME, "body").is_displayed())
Network and filter-list timing
First-run filter downloads can depend on network access, extension permissions, and the extension’s own update schedule. In CI, cache the extension artifact but avoid sharing a mutable browser profile between jobs. If the blocker’s lists are updated remotely, record the extension version and test date alongside failures.
Common failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Extension is ignored in headless mode | Legacy --headless or the old Headless binary |
Use --headless=new with a current Chrome, Chromium, or Chrome for Testing build. |
“Unknown switch” or startup failure for --load-extension |
Official Chrome-branded build at version 137 or newer | Use a CRX with add_extension(), or change the browser to Chromium/Chrome for Testing. |
| “Path is not a file” | The CRX path is wrong, relative, or unreadable | Resolve an absolute path, check permissions, and confirm the file exists before creating the driver. |
| “Manifest file is missing” | The unpacked path points to its parent directory | Point --load-extension directly at the directory containing manifest.json. |
| Profile is locked | Two processes share one user-data directory | Generate a unique writable profile per process and delete temporary profiles after the run. |
| Browser exits immediately | Driver, browser, and binary versions are incompatible, or a policy blocks the extension | Print browser and Selenium versions, pin a known-compatible browser/driver pair, and inspect startup logs and enterprise policy. |
| Page still shows ads | Filter lists are not initialized, the site uses a new delivery method, or the extension lacks permission | Wait for initialization, verify permissions and lists, and test a controlled fixture before blaming Headless. |
| Extension popup cannot be found | Wrong extension ID or popup filename | Inspect the extension manifest/build metadata and use the actual popup path. |
Security, reproducibility, and performance notes
- Use only extensions you trust. An extension can read or modify pages according to its permissions.
- Pin the browser distribution and extension artifact in CI. Chrome’s acceptance of loading flags is version-sensitive.
- Use isolated profiles and avoid placing secrets in command-line arguments or extension source directories.
- Headless removes the visible window; it does not make the browser faster in every workload. Extension startup, filter updates, page JavaScript, and network latency still dominate many runs.
- Record the browser channel, exact version, Selenium version, extension version, command-line arguments, and target URL for reproducibility.
Or skip the browser setup
If your goal is a clean screenshot rather than testing an extension’s behavior, ScreenshotNeo provides a website screenshot API and MCP server. One GET request 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 and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.
Its MCP server includes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every plan includes the full feature set, including full-page lazy-image loading, CSS-selector element capture, dark mode, device presets, custom viewport and retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification.
Rank #4
- 【Dreamy Rainbow Gaming Keyboard】K521 Gaming Keyboard Adopts a Different LED Backlight Design, Upgraded on the Traditional LED Backlight Effect, Making the Light More Penetrating, Giving You a More Dazzling Visual Effect, Making Your Gaming Process More Enjoyable
- 【One Touch Opens & Visual Feast】The K521 Red Dragon Keyboard has a One-Touch on/off Lighting Button for Added Convenience. It also has a Three-Position Adjustable Breathing Mode and a Four-Position Adjustable Brightness Lighting Mode
- 【Mechanical Feeling & Fast Tapping】The PC Keyboard Keys are Designed for Mechanical Feeling, Giving You a Better Feel During Use and the Ability to Trigger Keys Quickly, Allowing You to Win All Your Games
- 【19 Keys Anti-Ghosting Keyboard】Anti-Ghosting Ensures Every Button Can Be Triggered. This Allows You to Trigger Key Combinations In The Game Accurately, And Each Skill Can Be Accurately Released to Increase Your Winning Rate. Redragon K521 Will Be Your Perfect Partner
- 【12 Multimedia Combination Keys】The K521 Wired Gaming Keyboard is Equipped with 12 Multimedia Keys That Can Greatly Enhance Your Gaming/Office Efficiency and Make It More Convenient to Use
Use the ScreenshotNeo documentation for parameter details. A direct call looks like this:
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}`);
The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo free.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsFAQ
Can I load any Chrome extension in Headless?
New Headless supports extension loading paths, but each extension’s permissions, background behavior, filter updates, and compatibility still require validation in your chosen browser and Selenium versions.
Should I use a CRX or an unpacked directory?
Use a CRX when you need official Chrome-branded builds. Use an unpacked directory for Chromium or Chrome for Testing when you control the extension source or test artifact.
Best Value
- All-day Comfort: This USB keyboard creates a comfortable and familiar typing experience thanks to the deep-profile keys and standard full-size layout with all F-keys, number pad and arrow keys
- Built to Last: The spill-proof (2) design and durable print characters keep you on track for years to come despite any on-the-job mishaps; it’s a reliable partner for your desk at home, or at work
- Long-lasting Battery Life: A 24-month battery life (4) means you can go for 2 years without the hassle of changing batteries of your wireless full-size keyboard
- Simply plug the USB receiver into a USB port on your desktop, laptop or netbook computer and start using the keyboard right away without any software installation
- Simply Wireless: Forget about drop-outs and delays thanks to a strong, reliable wireless connection with up to 33 ft range (5); K270 is compatible with Windows 7, 8, 10 or later
Why does an old tutorial fail after a browser update?
It may rely on --load-extension with branded Chrome. Chrome 137 introduced the rejection of that switch in official Chrome builds.
Frequently Asked Questions
Can I load any Chrome extension in Headless?
New Headless supports extension loading paths, but each extension’s permissions, background behavior, filter updates, and compatibility still require validation in your chosen browser and Selenium versions.
Should I use a CRX or an unpacked directory?
Use a CRX when you need official Chrome-branded builds. Use an unpacked directory for Chromium or Chrome for Testing when you control the extension source or test artifact.
Why does an old tutorial fail after a browser update?
It may rely on --load-extension with branded Chrome. Chrome 137 introduced the rejection of that switch in official Chrome builds.
The Bottom Line
Use --headless=new. Load CRX files with add_extension(); use --load-extension only with Chromium or Chrome for Testing, not official Chrome-branded builds from version 137 onward.
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.
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 →

