Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Use the Chrome DevTools Protocol (CDP) command Browser.setDownloadBehavior with behavior: 'deny'. In Selenium, send that command through the driver’s DevTools/CDP channel before navigating to the page that might trigger a download. Add browserContextId when the rule should apply to one non-default browser context.
The direct CDP solution
Chrome exposes download policy through the Browser domain. The relevant operation is Browser.setDownloadBehavior; its purpose is to set the behavior when downloading a file. A minimal CDP request is:
{"method":"Browser.setDownloadBehavior","params":{"behavior":"deny"}}
Send it after creating the headless browser and before opening the page under test. The deny value prevents Chrome from accepting download requests under that browser policy. It is a browser-control setting, not an access-control feature: it does not replace server-side authorization, URL filtering, or malware protection.
Available behaviors
| Behavior | Effect | Additional parameter |
|---|---|---|
deny |
Reject downloads. | None. |
allow |
Permit downloads. | downloadPath is required. |
allowAndName |
Permit downloads while using the browser’s naming behavior. | downloadPath is required. |
default |
Return to Chrome’s default download handling. | None. |
The protocol also accepts eventsEnabled to control download events. Set browserContextId if you want the policy limited to a particular non-default context; omit it for the default browser context.
#1 Best Overall
Selenium with Python
Selenium 4 exposes a generic CDP method on the Python driver. This complete example starts headless Chrome, denies downloads, visits a URL, and then quits:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
try:
driver.execute_cdp_cmd(
'Browser.setDownloadBehavior',
{'behavior': 'deny'}
)
driver.get('https://example.com')
print(driver.title)
finally:
driver.quit()
Place the execute_cdp_cmd call before driver.get or before the click that starts a download. If your test creates an incognito or otherwise non-default context through a binding that exposes its identifier, include it in the parameter dictionary:
driver.execute_cdp_cmd(
'Browser.setDownloadBehavior',
{
'behavior': 'deny',
'browserContextId': context_id,
'eventsEnabled': True
}
)
The exact way to obtain a context identifier is binding- and version-dependent, so do not guess one. If the Python binding does not expose the Browser-domain command, use its generic CDP command facility rather than copying a method name from another language.
Selenium with Node.js
The Selenium JavaScript binding provides a DevTools command channel. Install Selenium with npm install selenium-webdriver, then run:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11const { Builder } = require('selenium-webdriver');
(async function () {
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.sendDevToolsCommand('Browser.setDownloadBehavior', {
behavior: 'deny'
});
await driver.get('https://example.com');
console.log(await driver.getTitle());
} finally {
await driver.quit();
}
})();
DevTools method names and availability follow the Selenium and Chrome versions installed in your environment. If sendDevToolsCommand is unavailable, use the binding’s version-specific CDP interface or a generic command endpoint and send the same method and parameters.
Selenium with .NET
Selenium .NET exposes the CDP channel through ExecuteCdpCommand. A minimal console application can configure the policy as follows:
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Collections.Generic;
var options = new ChromeOptions();
options.AddArgument("--headless=new");
using IWebDriver driver = new ChromeDriver(options);
var parameters = new Dictionary<string, object>
{
["behavior"] = "deny"
};
driver.ExecuteCdpCommand("Browser.setDownloadBehavior", parameters);
driver.Navigate().GoToUrl("https://example.com");
The .NET DevTools model also exposes SetDownloadBehaviorCommandSettings, with properties for Behavior, BrowserContextId, DownloadPath, and EventsEnabled. Those generated APIs are versioned, so select the namespace that matches the Chrome major version used by your test run.
Rank #2
Java and other Selenium bindings
Bindings differ in naming, but the operation is the same: open the driver’s DevTools or generic CDP channel and send Browser.setDownloadBehavior with behavior set to deny. Do not assume that a Python method name, a Java method name, and a JavaScript method name are interchangeable. Check the binding’s DevTools version and use its generic command mechanism when a typed Browser-domain wrapper is missing.
Recommended Free Tools
Browser context scope
Without browserContextId, the command applies to the default browser context. Supplying an identifier scopes the rule to one non-default context, which is useful when a test suite runs isolated sessions with different policies.
{"method":"Browser.setDownloadBehavior","params":{"behavior":"deny","browserContextId":"YOUR_CONTEXT_ID","eventsEnabled":true}}
Use the identifier returned by your automation framework; an arbitrary string will not select a real context. Configure each context explicitly when your suite creates more than one.
Why older examples use Page.setDownloadBehavior
Many older Selenium snippets call Page.setDownloadBehavior. Selenium’s Chromium protocol definition marks that Page-domain command deprecated and documents the newer Browser-domain operation. Prefer Browser.setDownloadBehavior for new integrations. Keep the Page command only when a legacy binding cannot send the Browser command, and treat that as a compatibility workaround rather than the current interface.
Verify that the policy is active
- Start the driver with the same headless Chrome binary used by CI.
- Send
Browser.setDownloadBehaviorwithdeny. - Navigate to a controlled test page containing a link or button that normally returns a downloadable response.
- Activate the control and assert the application reaches the expected post-click state without relying on a file appearing in the download directory.
- If you enabled
eventsEnabled, collect the binding’s download events and record the event outcome for diagnostics.
Do not use the existence of an old file as proof that the setting failed. Start each test with an empty temporary directory or a unique run directory, and make the assertion against the current run.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Troubleshooting
“Unknown command” or “method not found”
Your binding may expose only the deprecated Page-domain wrapper, or its DevTools namespace may target a different Chrome major version. Upgrade Selenium where possible, select the namespace matching the browser in CI, or send the Browser command through the generic CDP facility.
The command succeeds but a file still appears
Check ordering first: the policy must be sent before the navigation, popup, or click that initiates the download. Then check that the command was sent to the same driver session and browser context as the page. A second context can retain a different policy if it was created after your initial setup.
Rank #3
A context-specific rule has no effect
Confirm that the identifier belongs to the non-default context currently hosting the page. If you cannot obtain a valid identifier from the binding, omit the parameter and apply the rule to the default context, or use the binding’s context-management API.
Headless Chrome fails to start in CI
Download policy is separate from process startup. Resolve container issues first: use a Chrome-compatible Selenium release, provide a writable temporary directory, and apply only the sandbox and shared-memory flags required by your environment. A browser that never starts cannot receive a CDP command.
Tests pass locally but fail after a Chrome upgrade
Selenium’s DevTools APIs are versioned. Match the binding’s supported DevTools version to the Chrome major version installed on the runner, then rerun the download test. Avoid hard-coding a versioned namespace without pinning the corresponding browser image.
You need to stop unsafe URLs, not just downloads
deny controls browser download behavior. It does not authenticate requests, prevent a page from making an HTTP request, classify malware, or enforce an allowlist of destinations. Add server-side authorization, network filtering, and content inspection for those requirements.
Reliability, performance, and maintenance
- Set once per session: send the command during driver initialization instead of before every click.
- Keep sessions isolated: use a fresh context or driver when one test needs downloads allowed and another needs them denied.
- Pin compatible versions: the Chrome major version, Selenium package, and DevTools namespace should be selected as one tested combination.
- Log the policy: record the command result, browser version, context identifier, and test URL so failures can be diagnosed from CI artifacts.
- Use temporary storage for allow-mode tests: when a separate test must permit downloads, provide an explicit writable
downloadPathand clean it after the test.
The command itself is a small control-plane request; the expensive part of a test run remains browser startup, page loading, and JavaScript execution. Applying the policy early avoids wasted work and prevents a download from filling a CI workspace.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your actual goal is to obtain a clean image or PDF of a URL rather than exercise download behavior in a browser test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF; it does not replace Selenium when you must test a download button, but it removes the browser orchestration from capture jobs.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →See the ScreenshotNeo API documentation for all options. A cURL capture is:
Rank #4
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}`);
Before capture, ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Sign up for the free ScreenshotNeo plan.
FAQ
Does deny delete files that were already downloaded?
No. The setting governs download behavior after it is applied; clean up existing files separately in your test fixture or workspace.
Free tools Windows power users keep installed
One-click scans. No signup required.
Can I switch from deny to allow during one session?
Yes. Send the same Browser-domain command again with the desired behavior and, for allow or allowAndName, provide a valid writable downloadPath.
Should I use headless or headed Chrome for this setting?
The CDP command is independent of the display mode. Apply it to the driver session you are actually testing, whether that session runs with a headless flag or a visible window.
Is this a Selenium-only feature?
No. Selenium is one client for CDP. Any automation client that can send the Browser-domain command can use the same parameters.
Frequently Asked Questions
Does deny delete files that were already downloaded?
No. It affects download handling after the command is applied; remove old files separately.
Can I change the policy during a session?
Yes. Send Browser.setDownloadBehavior again with the new behavior and the required path for allow modes.
Is the setting limited to Selenium?
No. Selenium is only one CDP client; any client that can send the Browser-domain command can use it.
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.




