In Selenium, which Chrome preferences make a download land in a directory your test picked, with no save prompt?
answer
- The browser decides, not the driver
- Profile settings seeded at session start
- Two keys: a folder and a dialog
- Carried in the prefs experimental option
- One key names an absolute folder path
basics
~20 sSet the Chrome preference download.default_directory to an absolute path and download.prompt_for_download to false, passed as the prefs experimental option on ChromeOptions. The browser then writes the file into that folder on whichever machine runs the browser.
solid answer
~40 sChrome treats these as browser profile preferences, not command-line switches. Build a map with `download.default_directory` set to an absolute path you created and `download.prompt_for_download` set to `false`, then give it to `ChromeOptions` with `setExperimentalOption("prefs", prefs)` before the session starts. On a freight-tracking dashboard, clicking Export shipments then writes the CSV straight into that folder with no dialog, and the test asserts on the file itself. Two things bite people. The path is resolved by the browser process, so against a remote Grid node it names a directory on the node rather than on your machine. And nothing tells you the write finished, so poll for the file instead of reading it on the next line.
code
java · 24 linesPath exports = Files.createTempDirectory("freight-exports");
Map<String, Object> prefs = new HashMap<>();
prefs.put("download.default_directory", exports.toAbsolutePath().toString());
prefs.put("download.prompt_for_download", false);
prefs.put("download.directory_upgrade", true);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", prefs);
WebDriver driver = new ChromeDriver(options);
try {
driver.get("https://freight.internal/shipments");
driver.findElement(By.id("export-shipments-csv")).click();
Path csv = exports.resolve("shipments.csv");
new WebDriverWait(driver, Duration.ofSeconds(20))
.until(d -> Files.exists(csv)
&& !Files.exists(exports.resolve("shipments.csv.crdownload")));
System.out.println(Files.readString(csv));
} finally {
driver.quit();
}go deeper
Be ready to name the two Chrome preferences and say they are set on the options object before the browser starts. Knowing that the save dialog cannot be automated at all is expected here.
Explain the mechanics: preferences are written into the temporary profile at session creation, so they cannot change mid-run, and the path is resolved by the browser process rather than the test process.
Show the production judgment of isolating a download directory per test, clearing it before the click, and recognising that the same configuration cannot work when the browser lives on a remote node.
Own the tradeoff between asserting on a real downloaded artefact and checking the export at its service interface instead, given what a filesystem assertion costs in isolation and infrastructure.
## Where the download decision is actually made A **freight-tracking dashboard** with an "Export today's shipments" button gives a Selenium test an easy click and a hard follow-up: the exported CSV never enters the page. The browser receives the response, decides what to do with it, and writes bytes to a filesystem. The WebDriver protocol has nothing to say about any of that — there is no download command in the command set — so the only lever a test has is **the browser's own configuration**, seeded when the session starts. Chrome keeps that configuration in its **profile preferences**, the same values the Downloads section of `chrome://settings` edits. Selenium passes them as a map under the `prefs` key of `ChromeOptions`, and the driver writes them into the fresh temporary profile it builds for the session. - Preferences are profile settings, not launch switches: they belong in the `prefs` map, never in `addArguments`. - They are applied while the profile is created, so a test cannot re-point the download folder halfway through a run. - That profile is thrown away at `quit()`, so the settings never leak into your everyday Chrome profile. ## The preferences that matter | Preference | Value | Effect | |---|---|---| | `download.default_directory` | absolute path string | Finished downloads are written into this folder | | `download.prompt_for_download` | boolean | `false` writes silently; otherwise Chrome opens the Save As window | | `download.directory_upgrade` | boolean | `true` lets a new directory replace one remembered in the profile | `download.prompt_for_download` is the one that turns a hang into a pass. Left prompting, Chrome opens the **operating system's** file-save window. That window is not part of any document, has no DOM, and cannot be found, clicked or dismissed by WebDriver; `switchTo().alert()` does not reach it either, because that command addresses JavaScript dialogs inside the page. The test simply stalls until something times out. `download.default_directory` wants an **absolute** path to a directory that already exists and is writable by the account the browser runs as. A relative path is resolved against the browser's working directory, which is rarely what you meant. Creating one temporary directory per test and passing its absolute path is the usual shape. ## Wiring it into the session ```java Path exports = Files.createTempDirectory("freight-exports"); Map<String, Object> prefs = new HashMap<>(); prefs.put("download.default_directory", exports.toAbsolutePath().toString()); prefs.put("download.prompt_for_download", false); ChromeOptions options = new ChromeOptions(); options.setExperimentalOption("prefs", prefs); WebDriver driver = new ChromeDriver(options); ``` Firefox expresses the same intent with different keys — `browser.download.dir` alongside `browser.download.folderList` — while Edge, being Chromium-based, accepts the Chrome preference names through `EdgeOptions`. The shape is identical everywhere: configure the browser before the session, then treat the filesystem as the assertion surface. ## Which machine that path names This is the detail that turns a green local test red in the pipeline. The preference is interpreted **by the browser process**, on the host where that process runs. 1. A locally launched `ChromeDriver` runs the browser on your machine, so the folder is yours and ordinary file reads see the manifest. 2. A `RemoteWebDriver` against a Grid node runs the browser on the node, so the path names a directory on the node; your assertion looks at an empty local folder and fails. 3. Inside a container the directory must exist and be writable within the container; the host sees it only if it was mounted there. Case two is exactly why Selenium 4's Grid offers **managed downloads**, requested with the `se:downloadsEnabled` capability: the Grid takes over the download directory for that session and serves commands that copy the file back to the client. When the browser is remote, preferences alone cannot finish the job. ## Knowing the bytes actually arrived Choosing the folder does not tell you when the file is complete. `click()` returns once the click has been dispatched, not when the transfer ends, and Chrome writes into a `.crdownload` placeholder before renaming it to the real name. A dependable assertion is a small poll: 1. Create, or empty, the download directory before the click. 2. Click the export control on the dashboard. 3. Poll the directory until the expected name exists and no `.crdownload` sibling is left. 4. Read the file and assert on its contents. Clearing first matters for a second reason: when a file of that name is already present, Chrome does not overwrite it, it saves `manifest (1).csv`, and a test looking for `manifest.csv` cheerfully asserts on yesterday's shipments. ## Common wrong turns - Passing the directory as a capability rather than a preference; the key lives inside the `prefs` map. - Giving a relative path, then hunting for the file somewhere it was never written. - Trying to drive the Save As window with `Alert` or `Actions`; it is operating-system chrome, not page content. - Reading the file on the line after `click()` and blaming the intermittent failure on the network.
- Why does the same preference map do nothing useful when the test runs against a Grid node?The preference is read by the browser process, so it names a directory on the node's filesystem. The client never sees that folder. On Selenium 4 you request the `se:downloadsEnabled` capability instead and pull the file back over the session with the Grid's managed-download commands.
- The export button opens a PDF bill of lading in a viewer tab instead of downloading it. What changes?That is content the browser can render, so it displays rather than saves. In Chrome the preference `plugins.always_open_pdf_externally` set to `true` forces the PDF to disk; in Firefox `pdfjs.disabled` set to `true` does the same. The download directory preferences then apply as normal.
- Does setting these preferences affect the tester's real Chrome profile?No. The driver starts the browser against a fresh temporary user-data directory for each session and discards it at `quit()`, so the preferences live only for that session. If you deliberately point the session at your own profile directory, they do persist there.
saying these in an interview costs you the question
- Thinks the download directory is a command-line argument, not a preference
- Expects switchTo().alert() to dismiss the browser's Save As window
- Believes setting the directory alone suppresses the save prompt
- Assumes the configured path is on the machine running the test
- Asserts on the file immediately after click() with no polling