Skip to main content
Back to Blog
Guide
2026-05-11

Selenide File Download and Upload — Complete Guide 2026

Master Selenide file downloads and uploads. download(), uploadFile(), uploadFromClasspath, FileDownloadMode, proxy, and CI/CD patterns.

Selenide File Download and Upload Complete Guide

File uploads and downloads are notoriously fiddly in raw Selenium WebDriver. Chrome's headless mode handles downloads differently than headed mode, file dialogs are OS-native (and thus untestable via WebDriver), and verifying that a downloaded file is correct requires careful coordination between the browser and the test runner. Selenide solves all of this with a clean, cross-browser API: uploadFile() for inputs, uploadFromClasspath() for resource files, and download() for capturing downloads via proxy or browser interception.

This guide is a comprehensive walkthrough of Selenide's file handling APIs in 2026. We cover upload methods, download modes (HTTPGET, PROXY, FOLDER, CDP), proxy configuration for cross-browser downloads, custom timeouts, content verification, and the integration patterns for headless CI environments. Every code sample is working Java with Selenide 7+ and JUnit 5.


Key Takeaways

  • uploadFile() and uploadFromClasspath() handle file inputs without OS dialogs
  • download() captures the file the browser is downloading
  • FileDownloadMode controls how downloads are intercepted: HTTPGET, PROXY, FOLDER, CDP
  • PROXY mode works for any browser and HTTPS, with cookie forwarding
  • FOLDER mode uses the browser's download directory (simplest)
  • CDP mode (Chrome only) uses Chrome DevTools Protocol for native interception

File Upload Basics

import com.codeborne.selenide.SelenideElement;
import java.io.File;
import static com.codeborne.selenide.Selenide.$;

@Test
void uploadsAvatar() {
    open("/profile");
    File avatar = new File("src/test/resources/avatar.png");
    $("#avatar-input").uploadFile(avatar);

    $("#submit").click();
    $(".avatar-preview").shouldBe(visible);
}

uploadFile() sets the value on a <input type="file"> directly, bypassing the OS file dialog. Works in all browsers.


Upload from Classpath

For files bundled in your test resources:

@Test
void uploadsDocument() {
    open("/upload");
    $("#doc-input").uploadFromClasspath("samples/test.pdf");
    $("#submit").click();
}

The path is relative to src/test/resources/. Much cleaner than absolute paths.


Multi-File Upload

For inputs that accept multiple files (<input type="file" multiple>):

$("#files-input").uploadFile(
    new File("src/test/resources/a.txt"),
    new File("src/test/resources/b.txt"),
    new File("src/test/resources/c.txt")
);

Or from classpath:

$("#files-input").uploadFromClasspath("a.txt", "b.txt", "c.txt");

Drag-and-Drop Upload

For drag-and-drop upload zones (common in modern apps):

import org.openqa.selenium.Keys;
import static com.codeborne.selenide.Selenide.executeJavaScript;

// Simulate drag-and-drop by directly setting the input value behind the dropzone
$(".dropzone input[type=file]").uploadFromClasspath("photo.jpg");

Most drag-and-drop zones have a hidden file input that you can target directly.


File Download Basics

@Test
void downloadsInvoice() throws Exception {
    open("/invoices/123");
    File downloaded = $("a.download-invoice").download();

    assertTrue(downloaded.exists());
    assertEquals("invoice-123.pdf", downloaded.getName());
}

download() clicks the link and returns the downloaded file as a Java File.


FileDownloadMode

Selenide supports four modes for capturing downloads:

ModeHow it worksBrowser support
HTTPGETRe-fetches the href URL with the browser's cookiesAny
PROXYRoutes browser traffic through a local proxyAny
FOLDERUses browser's download directoryAny
CDPChrome DevTools Protocol native interceptionChrome/Edge

Configure:

import com.codeborne.selenide.FileDownloadMode;
Configuration.fileDownload = FileDownloadMode.PROXY;

HTTPGET Mode

The default. Simplest but limited:

  • Only works if the link has a direct href
  • Doesn't handle POST-based downloads
  • May trigger duplicate server requests
Configuration.fileDownload = FileDownloadMode.HTTPGET;

PROXY Mode

Robust mode that works for any download, including POST forms, AJAX, and dynamic URLs:

Configuration.proxyEnabled = true;
Configuration.fileDownload = FileDownloadMode.PROXY;

Selenide starts a BrowserMob proxy, configures the browser to use it, and captures responses. Cookies and headers are forwarded.

Drawback: requires the proxy library on classpath:

<dependency>
  <groupId>com.codeborne</groupId>
  <artifactId>selenide-proxy</artifactId>
  <version>7.5.0</version>
  <scope>test</scope>
</dependency>

FOLDER Mode

Uses the browser's actual download directory:

Configuration.fileDownload = FileDownloadMode.FOLDER;

Selenide configures Chrome to download to a managed temp folder and polls it for new files.

Pros: simplest, doesn't need proxy. Cons: doesn't work with all browsers identically. Race conditions if multiple downloads happen.


CDP Mode (Chrome)

Chrome DevTools Protocol native interception. Fastest and most reliable for Chrome:

Configuration.fileDownload = FileDownloadMode.CDP;
Configuration.browser = "chrome";

CDP is Selenide's recommended mode for Chrome and Edge in 2026.


Download Timeout

By default, downloads wait Configuration.timeout (default 4000ms). For large files, increase:

File big = $("a.big-file").download(Duration.ofSeconds(60));

Or globally:

Configuration.downloadsFolder = "build/downloads";
Configuration.timeout = 60_000;

Verifying Content

@Test
void downloadIsCorrectPdf() throws Exception {
    File pdf = $("a.report").download();

    // Verify it's a real PDF
    byte[] bytes = Files.readAllBytes(pdf.toPath());
    assertTrue(new String(bytes, 0, 4).equals("%PDF"));

    // Verify content with a PDF library
    try (PDDocument doc = PDDocument.load(pdf)) {
        String text = new PDFTextStripper().getText(doc);
        assertTrue(text.contains("Invoice #123"));
    }
}

Excel/CSV Download Verification

@Test
void exportsCsv() throws Exception {
    File csv = $("button.export").download();

    List<String> lines = Files.readAllLines(csv.toPath());
    assertEquals("Name,Email", lines.get(0));
    assertTrue(lines.get(1).startsWith("Alice,"));
}

For Excel:

try (XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(xlsx))) {
    Sheet sheet = wb.getSheetAt(0);
    assertEquals("Header", sheet.getRow(0).getCell(0).getStringCellValue());
}

Headless Chrome Downloads

In headless mode, the default download directory differs. Configure:

Configuration.headless = true;
Configuration.downloadsFolder = "build/downloads";
Configuration.fileDownload = FileDownloadMode.CDP;

CDP mode is reliable in headless. PROXY also works. FOLDER mode can be flaky in headless.


Custom Download Folder

Configuration.downloadsFolder = "target/test-downloads";

Files are saved here and the path is returned from download().


CI Patterns

In CI, ensure the downloads folder is created and cleaned between runs:

- name: Clean downloads
  run: rm -rf build/downloads target/test-downloads
- name: Run tests
  run: ./mvnw test
- name: Upload downloads on failure
  if: failure()
  uses: actions/upload-artifact@v4
  with:
    name: downloads
    path: build/downloads/

Uploading the downloads folder on failure helps debug download issues.


File Input Without Type=File

Some pages use custom UI elements (buttons that open file dialogs via JS). Find the underlying <input type="file"> even if hidden:

$("input[type=file]").uploadFromClasspath("photo.jpg");

If the input is genuinely missing (uses File System Access API), you'll need to skip the test in headless or use a custom workaround.


Common Pitfalls

Pitfall 1: Wrong file path. uploadFile requires an existing File object. Use File.getAbsoluteFile() and exists() checks before upload.

Pitfall 2: Stale download file. If the same test downloads multiple times, the second call might pick up the first file. Clean the downloads folder between calls.

Pitfall 3: Download mode mismatch. PROXY mode requires the proxy library. CDP mode requires Chrome. Pick the right mode for your test environment.

Pitfall 4: Headless download timing. Headless Chrome downloads can be slower. Increase timeouts.

Pitfall 5: Multi-platform paths. Use File.separator or forward slashes — never hardcode \.


Reference Card

ActionSelenide
Upload from file$.uploadFile(new File(...))
Upload from classpath$.uploadFromClasspath("name")
Upload multiple filesuploadFile(f1, f2, f3)
Download$.download()
Download with timeout$.download(Duration.ofSeconds(60))
Set download modeConfiguration.fileDownload = ...
Set download folderConfiguration.downloadsFolder = ...

Conclusion

Selenide turns file uploads and downloads from a Selenium pain point into a one-line operation. Pick CDP mode for Chrome-only environments, PROXY for cross-browser robustness, and FOLDER for simplest setup. Use uploadFromClasspath for test resources, and verify downloaded content with appropriate libraries. With proper CI artifact upload, debugging download issues becomes trivial.

For complementary patterns, see our headless Chromium guide and screenshot on failure guide.

Browse the QA skills directory for related browser testing patterns.

Selenide File Download and Upload — Complete Guide 2026 | QASkills.sh