July 5, 2026
Playwright vs Selenium for Handling Browser Downloads, PDF Exports, and File Save Prompts
A practical comparison of Playwright vs Selenium for browser downloads, PDF export testing, and file save prompts, including headless CI behavior, flaky edge cases, and when a platform like Endtest is easier to operate.
Modern test suites rarely fail because a download button is missing. They fail because the file is present but wrong, the PDF renders differently in headless CI, the save prompt blocks the flow, or the browser writes a renamed artifact that nobody accounted for.
That is why Playwright vs Selenium for browser downloads is not just a question of which API is nicer. It is a question of how much infrastructure you want to own, how much browser behavior you need to simulate, and how often your team wants to debug file-system and PDF edge cases instead of shipping features.
In download-heavy apps, the hardest part is usually not clicking the button. The hard part is verifying the thing that came out the other side: a CSV with the right rows, an invoice PDF with the right totals, a ZIP that unpacks correctly, or a generated file that is still readable when the browser runs headless in CI.
What usually breaks in download workflows
Before comparing tools, it helps to name the failure modes.
1. The file is downloaded, but the contents are wrong
This is the most common gap. A test clicks an export button, waits for a download event, and passes. Meanwhile the file contains the wrong date range, truncated text, malformed columns, or a PDF with a missing line item.
2. The browser changes the filename
Browsers can rename downloads when a file already exists, append (1) or similar suffixes, or infer a filename from the Content-Disposition header differently than the app expects. If your assertions assume one exact name, the test may become brittle across local, CI, and different browsers.
3. A native file save dialog appears
This matters mostly when the flow uses browser-native save prompts or when desktop automation is involved. Web automation tools are much better at handling browser-managed download events than native OS dialogs. As soon as the flow leaves the browser sandbox, the complexity goes up sharply.
4. Headless CI behaves differently
Headless runs may handle downloads, print-to-PDF, fonts, MIME types, or sandbox settings differently from local runs. A workflow that works on a developer laptop can fail in CI because the browser never had a writable download folder, or because the PDF generator used a different font stack.
5. The export is dynamic, not static
Many modern exports are generated from the current app state, for example invoices, statements, receipts, chart snapshots, or regulatory documents. That means you are not comparing a fixed fixture, you are validating data that was assembled just-in-time from UI, APIs, and server-side rendering.
A download test that only checks that “a file exists” is usually testing the transport, not the business rule.
Playwright for browser downloads
Playwright has a strong reputation for download handling because it treats the browser context as a first-class automation surface. It exposes download events, lets you save the file to disk, and supports assertions around the downloaded artifact without needing external browser driver setup.
The official docs are a good starting point: Playwright documentation.
A typical flow in Playwright looks like this:
import { test, expect } from '@playwright/test';
import fs from 'fs';
test('exports report as CSV', async ({ page }) => {
await page.goto('https://example.com/reports');
const downloadPromise = page.waitForEvent(‘download’); await page.getByRole(‘button’, { name: ‘Export CSV’ }).click();
const download = await downloadPromise; const path = await download.path(); expect(path).not.toBeNull();
const content = fs.readFileSync(path!, ‘utf-8’); expect(content).toContain(‘Account,Amount’); });
Why Playwright is strong here
- It has a clean download event model.
- It works well in headless and headed modes.
- It fits naturally into modern CI pipelines.
- It can inspect the file after download with normal Node.js libraries.
Where Playwright still takes work
Playwright gives you the primitives, not the full verification strategy. You still need to decide:
- where downloaded files should go,
- how to clean them up between runs,
- whether to inspect binary content, text content, or parsed structure,
- how to handle filename renaming,
- how to verify PDF layout versus extracted text.
That means Playwright is usually excellent for teams that are comfortable writing code around the browser API, but it can become maintenance-heavy if file validation becomes a recurring test category rather than an edge case.
Selenium for browser downloads
Selenium can absolutely validate browser downloads, but it typically requires more setup. Selenium is designed around WebDriver interactions, and download handling often depends on browser profile configuration, OS-level permissions, and extra glue code.
The Selenium documentation covers the core API, but file download behavior is one of the areas where teams usually end up relying on browser-specific preferences and local filesystem checks.
A Python example often looks like this conceptually:
from selenium import webdriver
from selenium.webdriver.common.by import By
import os
import time
options = webdriver.ChromeOptions() preferences = { “download.default_directory”: os.path.abspath(“downloads”), “download.prompt_for_download”: False, “plugins.always_open_pdf_externally”: True, } options.add_experimental_option(“prefs”, preferences)
driver = webdriver.Chrome(options=options) driver.get(“https://example.com/reports”) driver.find_element(By.ID, “export-csv”).click()
time.sleep(2) assert os.path.exists(“downloads/report.csv”)
Why Selenium is still relevant
- It is widely used in legacy suites.
- It is supported across many language stacks.
- Teams already running a WebDriver grid may prefer to extend it.
- It works for a broad range of browser automation tasks beyond downloads.
The cost of flexibility
Selenium’s download workflow usually depends on browser-level preferences and explicit file-system checks. That is fine if your team already has a stable framework and the download case is infrequent. It is less fine if every release requires multiple export validations across Chrome, Edge, Firefox, and Safari-like environments.
In practice, Selenium download tests are often more fragile because they are more sensitive to the browser profile, the driver version, and how the CI agent handles filesystem access.
PDF export testing is the real test, not the click
A lot of teams say they are testing downloads, but what they really mean is PDF export testing. This is a different problem.
A PDF export can fail in ways a file-existence check will never catch:
- text wraps differently,
- a table splits across pages incorrectly,
- a chart is missing,
- totals are present but numerically wrong,
- fonts differ and layout shifts,
- headers or footers disappear,
- the file opens but the content is incomplete.
If the artifact matters to users, then the test should validate the artifact, not just the browser event.
Playwright PDF export testing
Playwright handles the browser interaction well, but PDF verification usually needs a separate step. Common approaches include:
- extracting text from the PDF,
- converting pages to images for visual comparison,
- using a PDF parser to read metadata and structure,
- asserting on a server-generated response before the browser ever receives it.
For example, a Playwright test might validate the downloaded file name and then parse the PDF with a Node library:
import { test, expect } from '@playwright/test';
import pdfParse from 'pdf-parse';
test('invoice PDF includes total amount', async ({ page }) => {
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Download invoice PDF' }).click();
const download = await downloadPromise; const path = await download.path(); const data = await pdfParse(await download.createReadStream()!.read());
expect(data.text).toContain(‘Total’); });
This is powerful, but not trivial. You are now maintaining the browser flow, the PDF parsing layer, and the assertion layer.
Selenium PDF export testing
With Selenium, the browser automation side is usually harder, and the artifact validation side is still your responsibility. If the test suite needs to verify generated PDFs regularly, Selenium tends to push teams toward more custom helper code, more profile setup, and more browser-specific workarounds.
That is especially noticeable when a browser tries to open PDFs inline instead of downloading them. You may need to force external handling or tweak preferences, and that behavior is not equally consistent across browsers.
File save dialog automation is where web tools hit a wall
A key distinction matters here: browser download handling is not the same as native file save dialog automation.
If your app triggers a browser-managed download, Playwright and Selenium can usually manage it. If the flow opens a native OS save dialog, that is a different layer entirely. Traditional browser automation tools are not designed to manipulate native dialogs reliably across platforms.
This is why teams often adopt one of these patterns:
- configure downloads to save automatically,
- bypass native dialogs by setting browser preferences,
- test the backend export endpoint directly,
- use a platform or desktop automation layer that can deal with the file workflow end-to-end.
For web apps, the first two are common. For desktop, hybrid, or heavily controlled enterprise environments, the third or fourth pattern becomes more practical.
If your test depends on a native save dialog, you are no longer just testing the browser, you are testing the operating system and browser integration as well.
Headless CI behavior, the part teams underestimate
Download-heavy flows often pass locally and fail in CI because of environment assumptions. The usual culprits are boring but stubborn:
- the download directory is not writable,
- the container does not have expected fonts,
- the browser has sandbox restrictions,
- the CI job cleans up artifacts too early,
- file waits are too short,
- the application uses absolute paths or environment-dependent filenames,
- the PDF renderer behaves differently without a display.
Playwright generally gives you better ergonomics for headless CI because it is designed with modern automation pipelines in mind. Selenium can also run in CI, of course, but download workflows often require more environment tuning and more defensive coding.
A simple GitHub Actions pattern for Playwright might look like this:
name: e2e
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps
- run: npm test
Even here, download validation still depends on your test logic. The CI system can run the browser, but it will not tell you whether the exported file contains the right tax rate.
When Selenium is the better choice
Selenium still makes sense in several cases:
1. You already have a large Selenium suite
If download validation is one of many test categories in an existing WebDriver estate, adding a few download checks to the same stack can be cheaper than introducing a second framework.
2. Your team uses multiple languages
Selenium’s cross-language support is useful for organizations where QA, platform, and product engineering do not all use the same runtime.
3. You need compatibility with a mature grid or vendor setup
If your infrastructure already includes a Selenium Grid or a provider built around WebDriver, extending that stack may be operationally simpler than moving to a different model.
4. The download case is rare
If you only need occasional download validation, the setup cost may not justify a new tool.
The main tradeoff is that Selenium’s flexibility often comes with more glue code, especially for file handling and PDF verification.
When Playwright is the better choice
Playwright tends to win when the team is building new tests from scratch and download flows are a regular part of the product.
1. You need better browser download ergonomics
Playwright’s download model is straightforward and usually less brittle than WebDriver-based approaches.
2. You want faster developer iteration
The API feels closer to the browser behavior you are testing, which reduces the amount of framework code around the workflow.
3. You care about modern CI stability
Playwright’s design aligns well with containerized test execution, ephemeral workspaces, and artifact-based debugging.
4. You want to inspect downloaded files in code
If your team is comfortable writing file parsers and assertions, Playwright gives you a clean starting point.
That said, Playwright is still a code-first framework. If your organization wants fewer moving parts, less custom plumbing, or broader participation from QA and non-engineering teammates, a platform approach can be a better fit.
Where a platform approach changes the equation
This is where Endtest becomes relevant for teams that care about download-heavy flows but do not want to spend time building and maintaining the surrounding infrastructure.
Endtest is an agentic AI test automation platform, so instead of asking engineers to wire up every detail of download handling, it focuses on managed execution, low-code workflows, and reusable test steps. That matters when the real goal is not to maintain a download utility library, but to validate that the artifact is correct.
Two Endtest capabilities are especially relevant for this problem space:
- its PDF testing support, which is designed to validate generated documents rather than only detecting that a download happened,
- its AI-based assertions, which let you validate complex conditions in plain language instead of stitching together a long chain of brittle selectors or content checks.
That combination is attractive when the workflow is not just, “did the browser save a file,” but, “does the generated document match what the user requested, in the right language, with the right totals, and the right structure?”
Why platform workflows reduce friction
With a code-first stack, you own:
- browser setup,
- download path management,
- file cleanup,
- parser dependencies,
- PDF inspection logic,
- assertion utilities,
- CI troubleshooting.
With a managed platform, much of that plumbing is already wrapped into the workflow. That lowers setup overhead and makes it easier for QA engineers, not just developers, to author and maintain file-validation tests.
A practical example
If a support team asks, “Can we confirm the invoice PDF contains the correct customer name, tax, and total after the order completes?” a platform can often express that as a file validation scenario rather than a custom coding project. That is valuable when the test must be easy to understand, hand off, and update.
For teams evaluating the build-versus-buy decision for file workflows, the buyer guide for file upload/download validation is worth reviewing alongside your internal requirements, especially if your current Selenium suite is growing around repetitive file checks.
Decision criteria that actually matter
When choosing between Playwright, Selenium, and a platform approach, ask these questions:
How often do we validate downloads?
If it is weekly and simple, code-first may be fine. If it is daily across multiple workflows, maintenance cost becomes real.
Do we need to inspect the file contents?
If yes, you need more than browser automation. You need parsing, structure checks, or document validation.
Are we supporting PDFs specifically?
PDFs are not just files, they are document layouts. If that is central to your product, treat PDF validation as a first-class test category.
Do non-developers need to maintain these tests?
If QA, support, or product operations should own some of the validation, a platform with managed workflows can be easier to operate than a code repository.
Are we already invested in Selenium?
If the answer is yes, staying put may be the pragmatic choice. If not, Playwright often gives you a cleaner path for new browser-download automation.
Do we want to own the infrastructure?
This is the biggest hidden cost. Frameworks give you control, but they also give you responsibility. Managed platforms reduce setup and maintenance, which is often a better tradeoff for download-heavy validation.
A realistic comparison table
| Criterion | Playwright | Selenium | Platform approach like Endtest |
|---|---|---|---|
| Download event handling | Strong and ergonomic | Possible, but more setup | Managed, less setup overhead |
| PDF export validation | Good with custom parsing | Good with custom parsing, more glue | Strong fit for document validation |
| Native save dialogs | Not a good fit | Not a good fit | Better if workflow can be modeled without custom OS handling |
| Headless CI | Usually easier | Can work, but more tuning | Managed execution reduces environment burden |
| Maintenance cost | Moderate | Often higher for file flows | Lower for routine validation |
| Team accessibility | Developer-friendly | Developer-friendly, legacy-friendly | Better for mixed technical teams |
Common mistakes teams make
Treating download success as test success
A green test that only confirms a file was saved is often a false positive. Validate the contents.
Hardcoding filenames too early
If the application names files dynamically, match on patterns or inspect metadata rather than relying on a single exact string.
Ignoring cleanup
Download directories can accumulate artifacts and confuse later assertions. Clean them between tests or isolate them per run.
Forgetting browser differences
Chrome, Firefox, and WebKit-style behavior may differ in how they handle PDF opening and file naming. If the export matters to users, run cross-browser coverage deliberately.
Overusing sleeps
A sleep is not a download strategy. Prefer event-based waits, file existence checks with timeouts, or artifact assertions tied to a specific action.
A balanced recommendation
If your team is building a modern, code-first test stack and needs robust browser download handling, Playwright vs Selenium for browser downloads usually tilts toward Playwright because the API is more direct and the CI story is cleaner.
If your organization already runs a mature Selenium ecosystem, keeping download checks in Selenium may be the lowest-risk path, especially when the workflow is not central to your product.
If download validation is becoming a frequent, cross-team responsibility, or if the hard part is no longer the browser click but the document itself, a platform approach such as Endtest can be more practical. Its agentic AI workflow, PDF-focused testing, and AI assertions reduce the setup overhead that code-first tools leave on your team.
Final takeaway
Browser downloads are deceptively simple. The browser clicked a button, a file arrived, and everybody wants to move on. But the moment your product depends on invoices, exports, receipts, statements, or generated reports, file validation becomes a quality gate, not a checkbox.
Use Playwright when you want a modern, code-first way to inspect downloaded files with less ceremony. Use Selenium when you need to extend an existing WebDriver investment. Reach for a managed platform when the real business problem is reliable file and PDF validation with less infrastructure and less custom glue.
The right answer is not the tool with the most features, it is the one that lets your team validate the file users actually receive, without turning every export into a maintenance project.