Free tools Windows power users keep installed
One-click scans. No signup required.
Use Chrome’s new headless mode, Selenium’s Options object, and either a packaged .crx file or an unpacked extension directory. Add --headless=new before creating webdriver.Chrome; use add_extension() for a CRX, or --load-extension with Chromium or Chrome for Testing when you have an unpacked extension.
What works today
The reliable pattern is to select the browser build and extension format together. New Headless shares Chrome’s normal browser functionality while opening no visible desktop window. Chrome introduced this unified mode in version 112. The older Headless implementation was removed from the main Chrome binary in version 132, so tutorials that use an old headless switch are no longer a sound starting point.
Chrome’s extension end-to-end testing guidance specifically calls for --headless=new. It also warns that the old Headless implementation cannot load extensions. Selenium exposes two relevant loading mechanisms: add_extension() for a packaged CRX and the --load-extension=/absolute/path argument for an unpacked directory.
There is an important browser-distribution limitation. Beginning with Chrome 137, official Chrome-branded builds reject the unpacked-directory command-line switch. Chromium and Chrome for Testing continue to accept it. A recipe that worked with a branded google-chrome binary before that change can therefore fail without any change to its Python code.
#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.
Choose the browser and extension format
| Extension form | Selenium method | Browser choice | When to use it |
|---|---|---|---|
Packaged .crx |
options.add_extension(path) |
Use a Chrome-compatible build and verify the extension starts in your environment. | When you receive a release CRX and do not need to edit its files. |
| Unpacked directory | options.add_argument("--load-extension=" + path) |
Chromium or Chrome for Testing; not official Chrome-branded builds from Chrome 137 onward. | When developing, inspecting, or modifying an extension directory. |
These methods only load the extension. They do not prove that a particular ad blocker’s filter lists, service worker, permissions, or site-specific rules behave correctly in your test. The examples below use a placeholder path; supply an extension you are licensed and authorized to automate.
Install Selenium and prepare an isolated run
Install Selenium in the Python environment that will execute the test:
python -m pip install -U selenium
Use absolute paths. A unique writable user-data directory prevents cookies, extension state, and cached filter data from leaking between parallel runs. The following helper creates one and removes it after the browser exits.
from pathlib import Path
import shutil
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
extension_crx = Path("/absolute/path/to/ad-blocker.crx")
profile_dir = Path(tempfile.mkdtemp(prefix="selenium-chrome-"))
options = Options()
options.add_argument("--headless=new")
options.add_argument(f"--user-data-dir={profile_dir}")
options.add_extension(str(extension_crx))
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com/")
print(driver.title)
finally:
driver.quit()
shutil.rmtree(profile_dir, ignore_errors=True)
Selenium Manager normally locates a compatible driver. If your environment manages Chrome and the driver separately, ensure their major versions are compatible before debugging the extension.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →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
Load a packaged CRX
Minimal CRX example
For a packaged extension, call add_extension() before constructing the driver. The path must point to the actual CRX file, not its download URL or a directory containing it.
from pathlib import Path
import shutil
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
crx = Path("/opt/extensions/my-ad-blocker.crx").resolve()
if not crx.is_file():
raise FileNotFoundError(crx)
profile = Path(tempfile.mkdtemp(prefix="adblock-test-"))
options = Options()
options.add_argument("--headless=new")
options.add_argument(f"--user-data-dir={profile}")
options.add_extension(str(crx))
driver = webdriver.Chrome(options=options)
try:
driver.get("https://news.example/")
print("Loaded:", driver.current_url)
finally:
driver.quit()
shutil.rmtree(profile, ignore_errors=True)
Do not assume that a successful browser launch means blocking is active. Navigate to a controlled page containing a request or element your extension is expected to handle, then assert the user-visible result. Filter updates can be asynchronous, and some extensions require an initial permission or first-run action.
Load an unpacked extension with Chromium or Chrome for Testing
Directory-based example
An unpacked extension directory normally contains manifest.json at its top level. Pass its absolute directory path through --load-extension:
from pathlib import Path
import shutil
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
extension_dir = Path("/workspace/extensions/my-ad-blocker").resolve()
if not (extension_dir / "manifest.json").is_file():
raise FileNotFoundError("manifest.json not found in " + str(extension_dir))
profile = Path(tempfile.mkdtemp(prefix="chromium-adblock-"))
options = Options()
options.add_argument("--headless=new")
options.add_argument(f"--user-data-dir={profile}")
options.add_argument(f"--load-extension={extension_dir}")
# If Chrome for Testing is not on PATH, set its executable explicitly:
# options.binary_location = "/opt/chrome-for-testing/chrome"
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com/")
print(driver.title)
finally:
driver.quit()
shutil.rmtree(profile, ignore_errors=True)
Run this form with Chromium or Chrome for Testing. If the same command is pointed at an official Chrome-branded binary affected by the switch removal, Chrome can report an unknown or disallowed switch and start without the extension, or fail during startup. In that situation, either use a CRX with add_extension() or change the browser distribution.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
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*
Verify that the extension is actually doing its job
Prefer user-facing assertions
For ordinary integration tests, assert the outcome a user would see: an advertising element is absent, a test request is prevented, or a page-specific marker changes. Keep a control URL that should not be blocked so a broad failure is distinguishable from successful filtering.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
blocked_url = "https://test-site.invalid/page-with-known-ad"
driver.get(blocked_url)
# Example only: replace the selector and expected behavior with your fixture.
WebDriverWait(driver, 10).until(
lambda d: not d.find_elements(By.CSS_SELECTOR, ".known-ad-slot")
)
assert not driver.find_elements(By.CSS_SELECTOR, ".known-ad-slot")
Use a deterministic fixture rather than a live news site whenever possible. Live pages change markup, defer advertising requests, and can show different content based on geography, cookies, or consent state.
Inspect an extension page when necessary
Selenium cannot directly attach to an extension service worker. When a test genuinely needs extension data, navigate to an extension page such as chrome-extension://<extension-id>/popup.html and execute JavaScript there. The extension ID must come from the loaded extension’s manifest or your test fixture.
driver.get("chrome-extension://EXTENSION_ID/popup.html")
status = driver.execute_script(
"return document.body ? document.body.innerText : '';"
)
print(status)
Use this route sparingly. A popup may not represent background filtering, and its internal DOM is more likely to change than the page behavior your users depend on.
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
Make headless extension tests repeatable
Wait for the right condition
Do not rely on a fixed one-second sleep for filter initialization or lazy page content. Wait for a selector, a title change, a request result exposed by your fixture, or another explicit condition. Set a sensible page-load timeout and report the URL when a test fails.
Control profile state
Use a fresh profile for isolation. Reusing a profile can preserve consent choices, disabled-extension state, cached filter lists, and permissions. Conversely, if your test specifically covers a warm profile, create that profile once and document the state it contains.
Account for permissions and updates
Manifest permissions can affect whether an extension sees a page. A filter list that updates from the network can also make a test nondeterministic or fail in an offline build. Pin the extension artifact and provide a test fixture that does not depend on an unbounded third-party list.
Run parallel jobs safely
Never point two Chrome processes at the same user-data directory. Give each worker its own temporary profile and, when using unpacked extensions, its own copy if the test modifies files. Clean profiles after both successful and failed runs.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →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
Troubleshooting common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Chrome starts, but ads are unchanged. | The extension was not loaded, filter data is not ready, or the test page is outside its permissions. | Verify the CRX or directory path, inspect a known extension page, wait for a deterministic fixture, and check manifest permissions. |
“Unknown command line flag” or startup failure with --load-extension. |
The browser is an official Chrome-branded build affected by the switch removal. | Use Chromium or Chrome for Testing for an unpacked directory, or package the extension and try add_extension(). |
FileNotFoundError or “extension not found.” |
The path is relative, points to a ZIP instead of a CRX/directory, or the unpacked directory lacks a top-level manifest. | Resolve the path, check it before driver creation, and confirm manifest.json is at the directory root. |
| Session creation fails immediately. | Chrome, the driver, and Selenium are incompatible, or the profile directory is unwritable. | Update Selenium, use a matching browser/driver pair, choose a writable temporary directory, and capture the full driver log. |
| The test is flaky on a live site. | Ad scripts, consent flows, lazy content, and filter-list updates vary between runs. | Use a local or controlled fixture, explicit waits, a fresh profile, and assertions tied to stable selectors. |
| The extension popup is blank in headless mode. | The extension UI assumes a visible window or has no meaningful popup state. | Test page behavior instead; only inspect the extension page if the extension documents that headless use is supported. |
Performance, reliability, and security notes
- Startup cost: Loading an extension adds browser startup work, especially when filter lists initialize. Reuse one driver for a related test batch when isolation requirements allow it, rather than starting a new browser for every assertion.
- Network dependence: A blocker may need to download or refresh lists. For repeatable CI, make the required list state available in the test environment and fail clearly when it is missing.
- Headless parity: New Headless is intended to share regular Chrome functionality, but a particular extension can still depend on visible UI, notifications, or platform integration. Validate the exact extension and browser build you deploy.
- Security: Treat CRX files and unpacked code as executable software. Review their permissions, obtain them from a trusted source, and do not place production credentials in a profile used by third-party extensions.
- Observability: On failure, record the browser version, Selenium version, extension version, loading method, URL, and whether the run used a fresh profile. Those details distinguish a browser-policy change from a filter-rule problem.
Or skip the browser setup
If your actual requirement is to obtain a clean screenshot of a website rather than test an ad blocker’s behavior, ScreenshotNeo makes the capture a single HTTP request. It is not a browser extension and does not replace extension testing, but it removes common visual clutter before the capture: cookie and consent banners, newsletter popups, and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers.
ScreenshotNeo supports PNG, JPEG, WebP, and PDF output, with options for full-page capture, a CSS-selected element, device and viewport settings, dark mode, custom CSS or JavaScript, clicks, waits, blocked resources, cookies, headers, geolocation, resizing, caching, asynchronous jobs, bulk capture, and signed links. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
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)
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}`);
See the ScreenshotNeo API documentation for parameters and response headers. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it.
Frequently Asked Questions
Can one Selenium session load more than one extension?
Yes. Add each packaged CRX with a separate add_extension() call, or provide the unpacked directories together in the loading argument supported by your selected Chromium-based build. Test combinations separately because extensions can change one another’s page behavior.
Recommended Free Tools
Should I test an ad blocker against a production website?
Use a controlled fixture for CI. Production pages change markup, consent flows, advertising calls, and filter requirements, which makes a failure difficult to classify.
What if the extension only exposes settings through its toolbar UI?
A headless run may not provide the same visible toolbar workflow. Prefer manifest-backed configuration or a dedicated test page, and verify whether the extension officially supports unattended automation before depending on its UI.
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.

