How to Download Files in Playwright

Learn how to automate file downloads in Playwright, including setup, custom paths, and file validation with real examples.
April 6, 2026 13 min read
Test Digest Banner 1
Home Blog How to Handle File Downloads in Playwright (With Examples)

How to Handle File Downloads in Playwright (With Examples)

File downloads in Playwright look simple on the surface. A click triggers a download, a file gets saved, and the test moves on. That expectation breaks quickly once downloads start behaving differently across browsers, paths are not where they should be, or validations turn flaky.

I have seen tests pass locally and fail in CI just because the download was not captured correctly. In some cases, the file exists but cannot be accessed. In others, the download event is missed entirely, so the test has nothing to verify. These are not edge cases. They show up the moment file downloads become part of real test flows.

The interesting part is Playwright does not treat downloads like regular UI interactions. There is a specific flow behind how downloads are triggered, captured, stored, and accessed. If that flow is not handled correctly, even simple scenarios start failing.

In this guide, I will break down how file downloads actually work in Playwright, how to control where files are saved, and how to reliably validate them in automation tests without introducing flakiness.

How File Downloads Work in Playwright

File downloads in Playwright are not handled like typical UI actions such as clicking a button or typing into an input field. There is an underlying event-driven mechanism that controls how downloads are initiated and captured, and understanding this flow is critical for writing reliable tests.

When a user action triggers a download, for example clicking a download link or button, Playwright does not immediately give access to the file. Instead, it emits a download event that must be explicitly captured. This is where most implementations go wrong, especially when the test tries to interact with the file before Playwright has fully registered the download.

To make this reliable, Playwright introduces a structured flow that ensures the download is properly tracked and accessible.

What Happens When a File is Downloaded

At a high level, the process follows a clear sequence:

  • Action triggers download: A user interaction such as clicking a link or submitting a form initiates the download request
  • Download event is emitted: Playwright listens for a download event that represents the file being generated
  • Temporary storage is used: The file is stored in a temporary location managed by the browser context
  • Download object is created: Playwright provides a Download object that gives access to metadata and file handling methods
  • File becomes accessible: The file can then be saved, moved, or validated based on the test requirements

This flow ensures that the test does not rely on assumptions about timing or file availability.

Why This Flow Matters in Automation

Without handling downloads through this event-driven approach, tests can easily become unreliable. The main challenges include timing issues, inconsistent file paths, and incomplete downloads.

  • Timing issues: If the test tries to access the file before the download event is captured, it may fail intermittently
  • Unknown file locations: By default, files are stored in a temporary directory, which makes direct access difficult without explicit handling
  • Incomplete downloads: Without waiting for the download to finish, validations may run on partial or missing files

Setting Up the Playwright Environment for File Downloads

File downloads in Playwright rely heavily on how the environment is configured. A missing setup step can lead to downloads that never get captured, files that are hard to locate, or validations that fail inconsistently across local runs and CI pipelines.

A proper setup ensures that Playwright is installed correctly, the environment is validated, and the browser context is configured to handle downloads explicitly. With this in place, download flows become predictable and easier to debug.

Install Playwright for File Download Testing

Start by installing Playwright along with the required browser binaries so tests can run across supported environments and handle downloads consistently.

For JavaScript:

  • Initialize project: Set up a Node.js project using npm init
  • Install Playwright: Run npm install -D @playwright/test
  • Install browsers: Run npx playwright install to download supported browsers

For Python:

  • Install package: Use pip install playwright
  • Install browsers: Run playwright install to download browser binaries

This step prepares the environment for executing download-related test scenarios.

Verify the Playwright Installation

After installation, confirm that Playwright is running as expected. This step helps catch setup issues early before adding download-specific logic.

  • Run a sample test: Execute a basic Playwright test to confirm setup
  • Check browser launch: Ensure that browsers such as Chromium start correctly
  • Validate test execution: Confirm that tests run successfully in both local and CI environments

For example, running npx playwright test should execute tests successfully. Any failure at this stage points to environment issues that need attention.

Create a Browser Context That Supports File Downloads

Playwright uses isolated browser contexts for each test. To work with file downloads, the context needs to be configured to accept and manage downloads.

  • Enable downloads: Set acceptDownloads: true while creating the browser context
  • Control file handling: Define how downloaded files are accessed or stored
  • Maintain isolation: Each test context manages its own downloads, which keeps executions independent

With this configuration, Playwright captures download events and provides access to the Download object, which can then be used to save or validate files.

How to Automate File Downloads with Playwright (JavaScript)

Once the environment is ready, the next step is to automate how file downloads are triggered and captured in a test. In Playwright, this revolves around listening to the download event at the right time and then working with the Download object that gets created.

A common mistake is triggering the download first and then trying to capture it. This leads to missed events and unreliable tests. The correct approach is to start listening for the download before the action that triggers it.

Automating File Downloads: Step by Step

The flow involves three key steps. Start waiting for the download, trigger the action, and then work with the downloaded file.

import { test, expect } from '@playwright/test';



test('download file in Playwright', async ({ page }) => {

 await page.goto('https://example.com/download');



 // Start waiting for download before clicking

 const downloadPromise = page.waitForEvent('download');



 // Trigger the download

 await page.click('#download-button');



 // Capture the download

 const download = await downloadPromise;



 // Save the file to a custom path

 await download.saveAs('downloads/sample.pdf');



 // Validate file name

 expect(download.suggestedFilename()).toBe('sample.pdf');

});

What Happens in This Flow

Each step in the code maps directly to how Playwright handles downloads internally.

  • Wait for download event: page.waitForEvent(‘download’) ensures the test is ready to capture the file
  • Trigger download: The click action initiates the file download request
  • Capture Download object: The resolved promise provides access to the Download object
  • Save file: download.saveAs() moves the file from temporary storage to a defined location
  • Validate file: Metadata such as file name can be verified

How to Automate File Downloads in Playwright (Python)

The approach to handling file downloads in Playwright (Python) follows the same core principle as JavaScript. The test needs to start listening for the download event before triggering the action, so the file can be captured reliably.

Playwright’s Python API provides built-in methods to wait for downloads and interact with the Download object, which allows access to file metadata and storage operations.

Automating File Downloads: Step by Step

The flow involves waiting for the download, triggering it, and then saving or validating the file.

from playwright.sync_api import sync_playwright, expect



def test_download_file():

   with sync_playwright() as p:

       browser = p.chromium.launch()

       context = browser.new_context(accept_downloads=True)

       page = context.new_page()



       page.goto("https://example.com/download")



       # Start waiting for download before triggering action

       with page.expect_download() as download_info:

           page.click("#download-button")



       # Capture the download

       download = download_info.value



       # Save the file to a custom path

       download.save_as("downloads/sample.pdf")



       # Validate file name

       assert download.suggested_filename == "sample.pdf"



       browser.close()

What Happens in This Flow

This sequence follows how Playwright manages downloads internally, ensuring the file is captured and accessible.

  • Wait for download event: page.expect_download() sets up a listener before the action
  • Trigger download: The click action initiates the file request
  • Capture Download object: The context manager returns the Download object
  • Save file: download.save_as() moves the file to a defined location
  • Validate file: The file name or other attributes can be verified

How to Save Downloads to a Custom Location in Playwright

By default, Playwright stores downloaded files in a temporary location managed by the browser context. This works for basic scenarios, although real-world test flows often require more control over where files are stored so they can be accessed, shared, or validated later in the test.

Saving files to a custom location ensures that downloads are easier to track, persist across steps, and integrate with workflows such as reporting or CI artifacts.

1. How to Save a Download Using saveAs (JavaScript)

The most direct way to control file storage is by using the saveAs() method on the Download object.

const download = await downloadPromise;



// Save to a custom directory

await download.saveAs('downloads/report.pdf');

2. How to Save a Download Using save_as (Python)

In Python, the same behavior is achieved using the save_as() method.

download = download_info.value



# Save to a custom directory

download.save_as("downloads/report.pdf")

What to Consider When Using Custom Paths

Saving files to a custom location introduces a few practical considerations that impact reliability and maintainability.

  • Ensure directory exists: Create the target folder before saving, otherwise the operation can fail
  • Use relative paths: Keep paths relative to the project root so tests run consistently across environments
  • Handle file naming: Use dynamic naming if multiple downloads occur in the same test to avoid overwrites
  • Keep paths consistent in CI: Align directory structure with CI pipelines so downloaded files can be accessed as artifacts

For example, saving files under a /downloads folder within the project makes it easier to inspect outputs after test execution.

Verifying File Downloads in Playwright Automation

Triggering and saving a file is only part of the workflow. The real value comes from verifying that the correct file was downloaded, that it is complete, and that it matches the expected output. Without proper validation, tests may pass even when the downloaded content is incorrect.

In Playwright, verification can be done at multiple levels, starting from basic checks such as file name to deeper validation such as file content.

Validating File Name and Metadata

The simplest level of verification is to check whether the downloaded file matches the expected name.

  • Check suggested file name: Use suggestedFilename() in JavaScript or suggested_filename in Python
  • Match expected value: Compare the file name with what the application is supposed to generate
  • Catch incorrect downloads: Helps identify cases where a wrong file is served

For example, validating that a report download returns report.pdf ensures the correct file is triggered.

Verifying File Existence and Size

After saving the file, the next step is to confirm that the file exists and has meaningful content.

  • Check file presence: Ensure the file exists at the expected path
  • Validate file size: Confirm that the file size is greater than zero
  • Detect incomplete downloads: Small or empty files often indicate failed downloads

This level of validation ensures that the file is physically available and usable.

Validating File Content

For deeper validation, the file content can be inspected to ensure it contains the expected data.

  • Read file content: Open the file using standard file handling libraries
  • Match expected data: Verify specific values, text, or structure within the file
  • Use format-specific checks: For example, parsing JSON, CSV, or PDF content depending on the file type

For example, a CSV download can be validated by checking if required columns and values are present.

Handling Multiple Downloads

Some test scenarios trigger multiple file downloads in a single flow. These cases require careful handling to ensure each file is validated correctly.

  • Track each download event: Capture downloads individually using separate listeners
  • Use unique file names: Avoid overwriting files when saving
  • Validate in sequence: Ensure each file is verified against its expected output

This approach helps maintain clarity and avoids confusion when multiple files are involved.

Best Practices for Automating File Downloads in Playwright

Handling file downloads in Playwright becomes more reliable when the implementation follows a consistent structure. Small gaps in handling events, file storage, or validation can introduce flaky behavior that is difficult to debug later. These best practices focus on making download flows predictable, stable, and easy to maintain across different environments.

  • Start listening before triggering downloads: Always set up the download event listener before performing the action, so the file is captured reliably without timing issues
  • Enable download handling at the context level: Configure the browser context with acceptDownloads: true, so Playwright can capture and manage downloads properly
  • Use explicit save locations: Save files using saveAs() or save_as() to a known directory, so they can be accessed and validated consistently
  • Keep file paths environment-friendly: Use relative paths and a consistent folder structure, so tests run smoothly across local setups and CI pipelines
  • Validate beyond file existence: Check file name, size, and content, so the test confirms that the correct file is downloaded and usable
  • Handle multiple downloads carefully: Capture each download event separately and use unique file names, so files do not overwrite each other
  • Avoid hardcoded waits: Rely on Playwright’s event-based methods instead of static delays, so tests remain stable under different execution speeds
  • Clean up downloaded files when needed: Remove files after execution or manage them as test artifacts, so storage remains organized
  • Log and track download steps: Add logging around download actions and validations, so failures are easier to trace and debug

Conclusion

To download files in Playwright, set up the browser context with download support and ensure the environment is correctly installed. Capture the download event before triggering actions, save files to defined locations, and verify their names, sizes, and content. Additionally, apply consistent handling for multiple downloads to maintain reliable and repeatable test automation.