To download a file in headless Chrome, configure download behavior for the browser or automation context, set a writable destination directory, trigger the download, and wait for it to finish before using the file. The current Chrome DevTools Protocol documents Browser.setDownloadBehavior; Selenium’s JavaScript Chromium API also documents setDownloadPath(path), which uses a Page-level command. Choose the API supported by your Selenium binding and installed browser versions rather than assuming one method works everywhere.
What you need to configure
Headless mode controls how Chrome runs; it does not, by itself, configure where downloads go or allow them. Your automation must configure the active browser or browser context, choose a directory writable by the Chrome process, initiate the application’s download, and wait for completion before opening or moving the resulting file.
- Download behavior: The DevTools Protocol’s
Browser.setDownloadBehavioracceptsdeny,allow,allowAndName, anddefault. AdownloadPathis required when usingalloworallowAndName. See the Chrome DevTools Protocol Browser domain. - Destination: Use a directory that exists and that the user running Chrome can write to. In containers or CI, check the path from inside the browser’s runtime environment, not just from your local machine.
- Completion: Starting a click or receiving a download event is not the same as having a usable file. Wait for completion and verify the expected file before continuing.
The protocol describes Browser.setDownloadBehavior as “Set the behavior when downloading a file.” The specific command and event support available can depend on the Chrome/Chromium and automation versions in use.
Choose an API that matches your automation binding
| Approach | Scope and behavior | What to verify |
|---|---|---|
Browser.setDownloadBehavior |
Browser-level DevTools Protocol command. Supports behavior choices including allow and allowAndName; the path is required for either. |
Check that your DevTools client can send the Browser-domain command and that the installed Chrome version supports the command and options you use. Protocol reference. |
Selenium JavaScript setDownloadPath(path) |
The documented Chromium API validates that path is a directory and sends Page.setDownloadBehavior with allow. |
Use the API for the JavaScript binding/version actually installed. Do not treat this wrapper or its Page-level command as a universal Selenium API. Selenium JavaScript Chromium API. |
Prefer the browser-level protocol command when you are working directly with the DevTools Protocol and it is supported by your client. If you use Selenium, use the method documented for your language binding and version. The supplied official references do not establish a complete Chrome/ChromeDriver compatibility matrix, so check the installed versions rather than inferring compatibility from a code sample alone.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
- Intel Celeron N4120: 4 Cores & Threads, 1.1GHz Base Clock, Up to 2.6GHz Boost Clock, 4MB Cache, Intel UHD Graphics 600. The perfect combination of performance, power consumption, and value helps your device handle multitasking smoothly and reliably with four processing cores to divide up the work.
- 14" HD Display: 14.0-inch diagonal, HD (1366 x 768), micro-edge, anti-glare. See your digital world in a whole new way. Enjoy movies and photos with the great image quality and high-definition detail of 1 million pixels.
- Memory & Storage: 4 GB LPDDR4x & 64 GB eMMC Storage. Adequate high-bandwidth RAM to smoothly run multiple applications and browser tabs all at once. An embedded multimedia card provides reliable flash-based storage.
- Ports:2 x USB 3.0 Type-A,1 x USB 3.0 Type-C,1 x HDMI,1 x Headphone Jack
- Chrome OS: Chromebook is a computer for the way the modern world works, with thousands of apps. Enjoy the seamless simplicity that comes with Google Chrome and Android apps, all integrated into one laptop. It’s fast, simple, and secure.
Download a file with Selenium JavaScript
The following example uses Selenium’s JavaScript Chromium API. It creates a destination folder, configures that folder before clicking the download control, and waits for the expected file to appear and stop changing size. Replace the page URL, selector, and expected filename with values from your application. The example assumes a button or link with the selector #download starts the download and that the server supplies report.csv as the filename.
const { Builder, By } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const fs = require('node:fs');
const path = require('node:path');
const downloadDir = path.resolve('downloads');
const expectedFile = path.join(downloadDir, 'report.csv');
async function waitForStableFile(filePath, timeoutMs = 60000) {
const deadline = Date.now() + timeoutMs;
let previousSize = -1;
let stableChecks = 0;
while (Date.now() < deadline) {
try {
const stat = fs.statSync(filePath);
if (stat.isFile() && stat.size > 0 && stat.size === previousSize) {
stableChecks += 1;
if (stableChecks >= 2) return;
} else {
stableChecks = 0;
}
previousSize = stat.size;
} catch (error) {
if (error.code !== 'ENOENT') throw error;
stableChecks = 0;
}
await new Promise(resolve => setTimeout(resolve, 500));
}
throw new Error(`Download did not finish in time: ${filePath}`);
}
(async () => {
fs.mkdirSync(downloadDir, { recursive: true });
const options = new chrome.Options().addArguments('--headless=new');
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
try {
const chromium = driver.getExecutor ? driver : driver;
await chromium.setDownloadPath(downloadDir);
await driver.get('https://example.com/reports');
await driver.findElement(By.css('#download')).click();
await waitForStableFile(expectedFile);
console.log(`Downloaded ${expectedFile}`);
} finally {
await driver.quit();
}
})().catch(error => {
console.error(error);
process.exitCode = 1;
});
Install the JavaScript Selenium package in your project and ensure Chrome and its driver are available to Selenium. The method shown is specific to the documented JavaScript Chromium API; if your installed API does not expose setDownloadPath, do not silently substitute a method from another Selenium binding. Use the matching binding documentation or a DevTools client that supports the browser-level command instead.
The polling check above is an application-side safeguard, not a guarantee that every server’s filename is known in advance. If the server chooses a filename dynamically, inspect the directory for the file expected from that response or application flow. If a valid download can legitimately be empty, remove the stat.size > 0 condition and use a different completion check appropriate to that file.
Rank #2
- Storage: 16GB Flash Memory
- OS: Chrome OS
- Screen Size: 11.6"
Use the DevTools Protocol directly
When your automation exposes a DevTools Protocol session, send the browser-domain command before initiating the download. The essential command parameters are:
{
"method": "Browser.setDownloadBehavior",
"params": {
"behavior": "allow",
"downloadPath": "/absolute/path/to/downloads"
}
}
Replace the example path with the absolute path that Chrome can write to. The protocol also documents an optional browser-context identifier and an option to enable download events. Whether and how to attach those parameters depends on your automation client and whether you are configuring a particular browser context. Consult the Browser domain reference for the exact fields supported by the version you target.
The protocol documents Browser.downloadWillBegin and Browser.downloadProgress as download lifecycle events. These can help correlate a download with its completion state, but the documentation cautions that the completed event’s file path is not guaranteed to be set and does not guarantee that the file exists. Treat the event as a signal to check the filesystem, not as proof that the path is usable.
Rank #3
- Intel Processor Up to 2.80GHz, 4GB DDR4, 128GB Storage
- 15" FHD IPS Display, Intel UHD Graphics
- 1x USB Type C, 1 x USB Type A, 1x Headphone/Microphone Combo Jack, HDMI
- Fast WiFi and Bluetooth, Integrated Webcam
- Chrome OS, AC Charger Included, Pastel Silver
Wait for the right completion signal
There are two practical ways to decide when to read a downloaded file:
- Filesystem polling: Check for the expected output and confirm it is no longer changing. This works when the destination and filename are known, but needs a timeout and handling for server-chosen filenames.
- DevTools events plus filesystem verification: Listen for download lifecycle events, then confirm the resulting file exists and is ready before processing it. An event’s optional path alone is not sufficient evidence of file existence.
For either approach, avoid a fixed short sleep as the only completion check. Network time, server behavior, file size, and CI load can vary. Use a bounded wait, report a useful timeout, and preserve enough context—such as the destination, expected filename, and browser version—to diagnose failures.
Headless version notes
Chrome’s developer article shows Selenium using --headless=new, but command-line examples such as --dump-dom and --print-to-pdf are not a complete download setup: they do not replace configuring download behavior and a destination directory. See Chrome Headless mode.
Rank #4
- THE BETTER WAY TO LAPTOP – Imagine a Chromebook that’s as flexible as your day: thin and lightweight with built-in Google apps and stress-free security.
- TAKE HITS KEEP MOVING – Sleek, light, and built to last- the Chromebook 2-in-1 is just 0.69” thick and 3.3lbs. Enjoy long-lasting battery life, fast charging, and military-grade durability for nonstop productivity wherever life takes you.
- PERFORMANCE THAT MATCHES YOUR HUSTLE – Fuel your ideas with an Intel Core processor and 128GB storage. Boot up in under 10 seconds to start the day powerfully efficient.
- FLEX YOUR CREATIVITY ANYWHERE, ANYTIME – Create, work, or unwind your way with a versatile 2-in-1 design. Flip easily between laptop, tent, and tablet modes with a responsive touchscreen built for flexibility.
- BRILLIANT VIEWS AND IMMERSIVE AUDIO – See, hear, and create with awesome clarity. The WUXGA display brings rich detail to your work and play, while audio tuned by Waves MaxxAudio provides immersive, balanced sound.
There is also a specific old-headless transition: Chromium’s README states that as of milestone M132, old Headless functionality is no longer part of the Chrome binary and --headless=old has no effect. It directs users who need that old functionality to chrome-headless-shell. This is version context, not a claim that every download setup changes at M132. See the Chromium Headless README.
Troubleshooting failed downloads
The click succeeds, but no file appears
- Confirm the click actually triggers a download in the page’s normal flow rather than navigating to another page or opening a preview.
- Check that download behavior was configured before the click and that the configured directory is the one you are inspecting.
- Verify the Chrome process can write to that directory in the current container, user account, or CI worker.
- Wait for completion rather than checking immediately after the click.
Selenium reports that the download path is invalid
The JavaScript setDownloadPath(path) API requires an existing directory. Create it before calling the method, pass the intended path, and check that the path exists in the same runtime where Chrome runs. The API’s documented behavior is described in the Selenium JavaScript Chromium API.
The automation method is missing or rejected
Check the Selenium language binding and version, then verify that the browser and DevTools client support the command you intend to use. The JavaScript wrapper’s Page-level method is not a cross-language guarantee. When using a direct protocol session, check whether the browser-level Browser.setDownloadBehavior command and its selected parameters are available for your installed version.
Best Value
- 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..Voltage:5.0 volts
- 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).
The event says complete, but the file cannot be opened
Do not rely on the reported path alone. The protocol explicitly notes that the path may be unset and does not guarantee the file exists. Check the destination directory and validate the actual file before processing it.
The old headless flag appears to do nothing
If your setup depends on --headless=old, account for the Chromium M132 change: the old functionality is no longer included in the Chrome binary, and the flag has no effect there. The README points users needing old Headless functionality to chrome-headless-shell.
Or skip the browser setup
If your actual goal is a screenshot or PDF of a web page rather than downloading a file served by the page, ScreenshotNeo can return a screenshot or PDF from one GET request. It is not a substitute for downloading arbitrary files from an application. For page captures, cookie banners, newsletter popups, and chat widgets are removed before the shot; those steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response reports the page verdict and billing status. Its MCP server gives AI agents screenshot tools, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000.
cURL example; see the ScreenshotNeo documentation for parameters and response details:
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}`);
Sign up for 1,000 free screenshots a month with no card.
Frequently Asked Questions
Does the official documentation provide a Chrome and ChromeDriver compatibility table for these download APIs?
The cited protocol, Selenium, and Headless references do not provide a complete compatibility matrix. Check the documentation and supported commands for the exact versions installed in your environment.
Does this setup change by geographic region?
The cited documentation describes browser and automation behavior and does not specify regional variations.
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.
Recommended Free Tools




