File Upload & Download
Handle file upload inputs and capture downloaded files in Playwright without interacting with OS dialogs.
Uploading Files
File uploads in web applications use a hidden <input type="file"> element. Clicking it would normally open a native OS file-picker that automated tools cannot interact with. Playwright bypasses this entirely with setInputFiles(), which sets the file list directly on the input element. You can pass a single file path, an array of paths for multi-file uploads, or an object with a buffer and filename for in-memory file creation.
<input type="file"> and style a custom button. Use page.locator('input[type="file"]') to target the hidden input directly, even if it is not visible.Downloading Files
Playwright captures downloads by listening for the download event. Like popups and dialogs, you must start waiting for the event before triggering the download action. The Download object provides the suggested filename, the MIME type, and a stream or path to the downloaded content. Use download.saveAs(path) to persist it to a known location for post-test assertions.
Verifying Downloads
After saving, you can read the file content with Node.js fs, Python's built-in open(), or Java's Files.readAllBytes() to validate that the correct data was exported. This makes download testing fully automated and reproducible in CI environments.
import { test, expect } from '@playwright/test';
import path from 'path';
import fs from 'fs';
test('upload a single file', async ({ page }) => {
await page.goto('/upload');
// Target the hidden file input directly
await page.locator('input[type="file"]')
.setInputFiles('./fixtures/sample.pdf');
await expect(page.getByText('sample.pdf')).toBeVisible();
await page.getByRole('button', { name: 'Upload' }).click();
await expect(page.getByText('Upload complete')).toBeVisible();
});
test('upload multiple files', async ({ page }) => {
await page.goto('/upload');
await page.locator('input[type="file"]').setInputFiles([
'./fixtures/report-jan.csv',
'./fixtures/report-feb.csv',
]);
await expect(page.getByText('2 files selected')).toBeVisible();
});
test('download a file and verify content', async ({ page }) => {
await page.goto('/reports');
// Start expecting download before triggering it
const [download] = await Promise.all([
page.waitForEvent('download'),
page.getByRole('button', { name: 'Export CSV' }).click(),
]);
const savePath = `/tmp/${download.suggestedFilename()}`;
await download.saveAs(savePath);
const content = fs.readFileSync(savePath, 'utf-8');
expect(content).toContain('Date,Revenue');
});
import com.microsoft.playwright.*;
import java.nio.file.*;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
class FileUploadDownloadTest {
void uploadFile(Page page) {
page.navigate("/upload");
page.locator("input[type='file']")
.setInputFiles(Paths.get("fixtures/sample.pdf"));
assertThat(page.getByText("sample.pdf")).isVisible();
page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Upload")).click();
assertThat(page.getByText("Upload complete")).isVisible();
}
void downloadFile(Page page) throws Exception {
page.navigate("/reports");
Download download = page.waitForDownload(() ->
page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Export CSV")).click()
);
Path savePath = Paths.get("/tmp/" + download.suggestedFilename());
download.saveAs(savePath);
String content = new String(Files.readAllBytes(savePath));
assert content.contains("Date,Revenue");
}
}
from playwright.sync_api import Page, expect
from pathlib import Path
def test_upload_single_file(page: Page):
page.goto("/upload")
# Target hidden file input
page.locator('input[type="file"]').set_input_files("fixtures/sample.pdf")
expect(page.get_by_text("sample.pdf")).to_be_visible()
page.get_by_role("button", name="Upload").click()
expect(page.get_by_text("Upload complete")).to_be_visible()
def test_upload_multiple_files(page: Page):
page.goto("/upload")
page.locator('input[type="file"]').set_input_files([
"fixtures/report-jan.csv",
"fixtures/report-feb.csv",
])
expect(page.get_by_text("2 files selected")).to_be_visible()
def test_download_and_verify(page: Page):
page.goto("/reports")
with page.expect_download() as dl_info:
page.get_by_role("button", name="Export CSV").click()
download = dl_info.value
save_path = Path("/tmp") / download.suggested_filename
download.save_as(save_path)
assert "Date,Revenue" in save_path.read_text()
Written by PV
© 2026 All Rights Reserved