Resource library

QA How-To

How to Assert a downloaded PDF in Selenium (2026)

Learn selenium how to assert a downloaded PDF using Java, PDFBox, controlled download folders, robust waits, content checks, and CI-safe cleanup.

24 min read | 3,264 words

TL;DR

For selenium how to assert a downloaded PDF, use a layered, risk-based approach and verify outcomes with reliable tooling. The examples and model answers below show production-ready patterns for 2026.

Key Takeaways

  • Build evidence around selenium how to assert a downloaded PDF, not memorized definitions.
  • Use deterministic waits and observable outcomes instead of fixed delays.
  • Separate environment failures from product defects with logs and artifacts.
  • Keep tests independent, readable, and safe for parallel CI execution.
  • Test realistic risks across happy paths, boundaries, and failure states.
  • Explain tradeoffs clearly, including what you would not automate.

selenium how to assert a downloaded PDF is the focus of this practical guide. Selenium how to assert a downloaded PDF is a layered problem: prove the server returned a PDF, prove the browser or test saved the intended file, parse it outside the browser, and assert stable business content. A file-exists check alone can pass with a stale, empty, HTML, or wrong customer's file.

The reliable 2026 pattern uses core Selenium commands for the download and file wait, then a Java helper registered in JUnit setup for PDF parsing. This guide uses Apache PDFBox through the maintained org.apache.pdfbox package and avoids non-existent commands such as a nonexistent built-in PDF parser.

TL;DR

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>4.35.0</version>
</dependency>
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>3.0.5</version>
  <scope>test</scope>
</dependency>
Assertion layer What it proves What it does not prove
Response headers and status Correct download contract File reached disk or content is correct
File size and %PDF- bytes A nontrivial PDF-like file exists Pages render or values are correct
Parsed page count and text Structural and semantic content Exact visual layout
Rendered page comparison Visual appearance Business meaning by itself

The example needs the Java helper configured below. Keep assertions aligned with the actual PDF requirement rather than treating one technique as complete coverage.

1. Selenium How to Assert a Downloaded PDF by Risk: selenium how to assert a downloaded PDF

Start with the reason the PDF matters. An invoice must contain the correct account, line items, taxes, currency, total, issue date, and identifier. A report may need a title, filters, generated timestamp, rows, totals, and page headers. A certificate may require a recipient, qualification, date, and verification value. Those facts define the oracle.

Break the path into contracts:

  1. The UI exposes the download only to an authorized user.
  2. The request uses the intended document identifier and returns a successful response.
  3. Headers describe a PDF attachment and safe filename.
  4. The saved bytes form a readable PDF rather than an error page.
  5. Parsed pages contain the expected semantic values.
  6. Visual, accessibility, form, signature, or archival requirements pass through specialized checks if applicable.

This decomposition makes failures useful. A 403 is not reported as "missing invoice text." A malformed PDF is not confused with a wrong total. A font clipping issue does not need to be diagnosed from raw extracted text.

Decide whether the test needs the browser download. If you are verifying the button, filename, and browser integration, trigger the UI. If you are verifying many document data combinations, call the download endpoint with an HTTP client, write the bytes, and parse them. Keep a small UI path plus broader service-level document tests.

2. Install Apache PDFBox and Configure the Downloads Folder: selenium how to assert a downloaded PDF

Install Selenium and Apache PDFBox as development dependencies in an existing Java project. Use the version selected and locked by your repository rather than copying an unreviewed global tool:

Path downloadDir = Files.createTempDirectory("pdf-downloads");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", Map.of(
    "download.default_directory", downloadDir.toAbsolutePath().toString(),
    "download.prompt_for_download", false,
    "plugins.always_open_pdf_externally", true));
WebDriver driver = new ChromeDriver(options);

Set a deterministic downloads folder. downloadsFolder is a supported Selenium configuration option, and the default is target/downloads. An explicit value makes helper code and CI artifacts easier to understand.

static Path waitForPdf(Path directory, Duration timeout) throws Exception {
  long deadline = System.nanoTime() + timeout.toNanos();
  while (System.nanoTime() < deadline) {
    try (Stream<Path> files = Files.list(directory)) {
      Optional<Path> pdf = files.filter(p -> p.toString().endsWith(".pdf"))
          .filter(p -> !p.toString().endsWith(".crdownload"))
          .findFirst();
      if (pdf.isPresent() && Files.size(pdf.get()) > 4) return pdf.get();
    }
    Thread.sleep(200);
  }
  throw new TimeoutException("PDF was not downloaded");
}

Selenium clears screenshots, videos, and downloads before selenium run when trashAssetsBeforeRuns is enabled, which is the normal default behavior. Do not make an individual test depend only on run-level cleanup. Interactive sessions, reruns, and a failed setup can leave files behind. Remove the expected file before the action or create a unique document and filename.

Review the Selenium configuration guide when a monorepo or multiple testing types use different artifact paths. Resolve every task path from the project root rather than assuming the shell's working directory.

Add target/downloads to version-control ignore rules. Treat generated PDFs as test artifacts, not source. In CI, upload a failed document only when it is safe. Invoices, reports, and identity documents can contain sensitive data, so apply redaction, access control, and retention policy.

3. Trigger the UI Download and Wait for the File

If the filename is deterministic, the simplest path is to click the real link and use a filesystem polling helper. The command retries reading until the file exists and its chained assertions pass, subject to its timeout. Passing null as encoding returns bytes through Java byte arrays support.

Path pdf = waitForPdf(downloadDir, Duration.ofSeconds(20));
byte[] bytes = Files.readAllBytes(pdf);
assertArrayEquals(new byte[]{'%', 'P', 'D', 'F', '-'}, Arrays.copyOf(bytes, 5));
try (PDDocument document = Loader.loadPDF(pdf.toFile())) {
  assertTrue(document.getNumberOfPages() > 0);
  String text = new PDFTextStripper().getText(document);
  assertTrue(text.contains("INV-2048"));
}

Register the intercept before clicking so the request cannot outrun the observer. Match the narrowest stable route. Do not assert an exact content length unless the requirement guarantees it, because PDF metadata, compression, and library updates can change bytes without changing the document.

A %PDF- prefix is a useful format sanity check, not a full validator. Parsing in the next step proves that a PDF library can open the document and enumerate its pages. If your application streams a file slowly, the filesystem helper may see an intermediate file. Chained assertions retry the entire query, but a parser task called too early will not. First wait until bytes and any known minimum size are stable enough for your product.

4. Parse the PDF in a Selenium Java Task

Selenium test commands execute in the browser-side runner, while JUnit setup tasks execute in Java. PDF parsing and direct filesystem access belong in the Java process. Register a task that accepts a project-relative path, confines reads to the configured downloads directory, opens the bytes with Apache PDFBox, and returns JSON-serializable data.

@Test
void downloadsAndValidatesInvoicePdf() throws Exception {
  driver.get(baseUrl + "/invoices/INV-2048");
  driver.findElement(By.linkText("Download PDF")).click();
  Path pdf = waitForPdf(downloadDir, Duration.ofSeconds(20));
  try (PDDocument document = Loader.loadPDF(pdf.toFile())) {
    String text = new PDFTextStripper().getText(document).replaceAll("\\s+", " ");
    assertAll(
        () -> assertTrue(document.getNumberOfPages() > 0),
        () -> assertTrue(text.contains("INV-2048")),
        () -> assertTrue(text.contains("Ada Tester")));
  }
}

The path guard prevents a test input from turning the task into an arbitrary file reader. Apache PDFBox receives a plain Uint8Array rather than Java's Buffer subclass. The task destroys the document in finally so parser resources are released even when extraction fails.

5. Assert Stable Text, Page Count, and Business Values

Add a Java shape for the serialized task result and normalize only what the requirement permits. PDF text extraction may insert different whitespace or return visual columns in content-stream order. Do not compare the entire extracted document to one giant string unless exact text serialization is itself a contract.

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>4.35.0</version>
</dependency>
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>3.0.5</version>
  <scope>test</scope>
</dependency>

Derive expected values from controlled fixture data or the authoritative service response, not by copying the same presentation code used to generate the PDF. If the test calculates tax with the production helper and the PDF uses that helper, both can reproduce the same bug. Use explicit examples or an independent oracle.

For tables, assert stable row keys and totals. Extracted order may interleave columns, so a raw substring can be fragile. If table structure is a business requirement, consider a parser that exposes coordinates and reconstruct rows, or validate the source report data at the API layer and keep targeted content plus visual PDF checks.

6. Download the PDF Through an HTTP client for Broader Coverage

Browser downloads are appropriate for one or a few wiring tests. Data-rich document verification is often faster and easier through the endpoint. an HTTP client is a standard Java operation and can request a binary response. The browser's cookies are normally available to the request, so it can exercise the authenticated endpoint in the same test context.

Path downloadDir = Files.createTempDirectory("pdf-downloads");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", Map.of(
    "download.default_directory", downloadDir.toAbsolutePath().toString(),
    "download.prompt_for_download", false,
    "plugins.always_open_pdf_externally", true));
WebDriver driver = new ChromeDriver(options);

This method does not prove that clicking the UI initiates the download or that the browser uses the suggested filename. Keep an end-to-end test for that contract. In return, API-driven tests make it easier to generate invoices with boundary values, call the document service, and assert results without navigating repeatedly.

For a POST-based export, send the documented body and verify anti-forgery requirements. Avoid inventing a test-only download method if the application already exposes a supported authenticated endpoint.

7. Handle Dynamic and Content-Disposition Filenames

Timestamps and random suffixes make file discovery harder and stale-file mistakes more likely. The best product contract often uses a deterministic business identifier in the filename. If the server must generate a dynamic name, observe Content-Disposition and verify it safely.

Header values can use quoted filename or RFC 5987 filename* syntax. Production parsing should use a maintained content-disposition parser rather than a casual split when international names matter. In a focused test with a documented simple header, extract the expected known pattern and reject path separators.

When the UI download filename cannot be known before the response, a Java helper can list PDF files with names and modification times. Capture the directory snapshot before clicking, wait for the network response, then poll until exactly one new file appears. Do not select "the newest PDF" from an unclean shared folder because another parallel test may win the race.

An even safer design creates a worker-specific subfolder, if the browser and environment support directing downloads there, or uses a unique invoice identifier and expected filename. Selenium parallel workers generally have separate checkout processes in CI, but local and custom runners can share storage. Design explicitly rather than relying on an accident of the runner.

Sanitize filenames before building paths. Reject .., slash, backslash, NUL, and unexpected extensions. The parser task should continue enforcing that the resolved path stays under downloads.

8. Assert Metadata, Links, Annotations, and Forms Deliberately

Text and page count do not cover every PDF feature. Apache PDFBox can expose document metadata with document.getMetadata() and page annotations with page.getAnnotations(). Extend the Java helper only for requirements you actually own, and return a small serialized representation rather than library objects.

Metadata can include title, author, subject, keywords, creation date, and custom information, but producers vary. Do not fail a business test on incidental generator metadata unless a standard or requirement controls it. Creation timestamps are especially poor snapshot values.

Links should be checked for label, target, protocol, and authorization risk. An extracted annotation may identify the target even when visible text extraction is imperfect. For external links, avoid calling third-party production services from a routine test. Validate the URL structure or use an approved controlled endpoint.

Interactive forms require field-level assertions and possibly rendering or viewer integration. A flattened form may appear visually correct but have no editable fields, which can be correct or incorrect depending on the requirement. Digital signatures need a library and trust policy that can validate cryptographic integrity, certificate chain, signing time, revocation behavior, and allowed modifications. A visible image of a signature is not a digital-signature validation.

PDF/A or accessibility conformance also requires specialized validators and human review. Selenium can orchestrate those command-line tools through a narrowly scoped Java helper, but it does not provide a built-in conformance assertion.

9. Separate Text Assertions From Visual PDF Testing

Apache PDFBox text extraction does not tell you whether a total is clipped, a logo overlaps a heading, a font is missing, a table runs off the page, or a footer covers the last row. If layout is contractually important, render selected pages to images in a controlled Java or CI step and compare them with reviewed baselines or assert regions.

Visual comparison needs stable inputs: fixed data, fonts, locale, time zone, renderer, page size, and PDF producer version. Define an intentional update process for baselines. A broad pixel tolerance can hide a small but important digit change, while zero tolerance can fail on harmless rasterization differences. Combine visual comparison with semantic assertions.

Test responsive HTML before PDF generation when the source template is web-based. Component tests can catch layout and accessibility problems faster. Then retain PDF rendering checks for page breaks, print CSS, embedded fonts, headers, footers, and final output.

Scanned PDFs contain page images rather than an extractable text layer. Apache PDFBox may return little or no text. Use a controlled OCR pipeline when the requirement is to recognize scanned content, and validate OCR confidence and language. OCR output is probabilistic, so do not reuse text-extraction expectations blindly.

For regulated output, ask whether byte identity, visual identity, semantic values, conformance, or human approval is required. These are different oracles and deserve different tooling.

10. Prevent Stale Files and Parallel CI Collisions

A stale PDF is the most dangerous false pass in this pattern. The test can skip or fail the download, then parse yesterday's correct file. Remove the expected artifact before the action through a safe Java helper, or create a unique business object whose filename has never existed in the run.

The same isolation principles apply to other files. See the Selenium file download testing guide for broader filename, browser, and CI scenarios beyond PDF parsing.

Register a restricted cleanup task beside readPdf. Resolve the path under the downloads root and call Java's rm(path, { force: true }). Return null, because Selenium tasks must not resolve to undefined. Keep the same path guard used for reads.

In parallel CI, give each worker unique application data and artifact names. Include a CI node index or test-run identifier that is not secret. Never share one invoice record if tests can regenerate or mutate it. Upload PDFs on failure selectively and protect access.

Do not use an arbitrary Thread.sleep(5000) to wait for disk. the filesystem helper retries. For especially large streaming output, add a Java helper that reports size and modification time, and poll until the documented completion signal is reached. A stable size across a short interval can help, but the network response completing plus successful parser open is a stronger signal.

If parsing intermittently reports a truncated document, preserve the response timing, file size sequence, and raw file. Determine whether the browser finished writing after the intercepted response, the server ended early, or the parser ran before rename from a temporary download.

11. Build a Reusable Selenium How to Assert a Downloaded PDF Helper

Keep helpers small and typed. A command can wait for bytes and call the task, but business assertions should remain in the test so expected content is visible. Avoid a universal helper with dozens of booleans for text, snapshots, signatures, metadata, and OCR.

static Path waitForPdf(Path directory, Duration timeout) throws Exception {
  long deadline = System.nanoTime() + timeout.toNanos();
  while (System.nanoTime() < deadline) {
    try (Stream<Path> files = Files.list(directory)) {
      Optional<Path> pdf = files.filter(p -> p.toString().endsWith(".pdf"))
          .filter(p -> !p.toString().endsWith(".crdownload"))
          .findFirst();
      if (pdf.isPresent() && Files.size(pdf.get()) > 4) return pdf.get();
    }
    Thread.sleep(200);
  }
  throw new TimeoutException("PDF was not downloaded");
}
Path pdf = waitForPdf(downloadDir, Duration.ofSeconds(20));
byte[] bytes = Files.readAllBytes(pdf);
assertArrayEquals(new byte[]{'%', 'P', 'D', 'F', '-'}, Arrays.copyOf(bytes, 5));
try (PDDocument document = Loader.loadPDF(pdf.toFile())) {
  assertTrue(document.getNumberOfPages() > 0);
  String text = new PDFTextStripper().getText(document);
  assertTrue(text.contains("INV-2048"));
}

The helper first establishes format and size, then parses. The test can normalize whitespace and assert its own domain facts. Because a PDFBox parser helper does not retry its internal filesystem read, the preceding the filesystem helper is important.

If the task input grows to include a password or options, pass a plain object and validate every property. Do not log passwords. Keep task code under unit test where parsing rules become complex.

12. Debug Failures and Protect Document Data

Classify failure before editing timeouts. A missing request suggests UI wiring, authorization, routing, or selector failure. A non-200 response belongs to the service or test setup. An HTML prefix often means a login page or proxy error was saved as .pdf. A valid signature with parser failure can indicate truncation, encryption, corruption, or unsupported features. Correct text with visual failure belongs to rendering.

Log safe facts: status, content type, sanitized filename, byte length, page count, and a correlation identifier. Avoid dumping the entire extracted document, response body, or PDF into console output. CI logs can have broader access and longer retention than the source application.

Password-protected PDFs require the parser's supported password option and secret-safe task input. Test wrong-password behavior deliberately. Never commit a real customer's password or document. For signed and confidential documents, coordinate artifact policy before enabling upload-on-failure.

Use fixture builders to create synthetic names, addresses, account numbers, and line items. Keep the data realistic enough to expose wrapping, Unicode, right-to-left, long values, and pagination defects without using production records. Test malicious text such as markup-like characters at the source layer to ensure the PDF generator escapes and renders it safely.

Finally, pin dependencies through the lockfile and review PDF parser security updates. Parsing is complex input handling. Run untrusted documents only in an appropriately isolated test environment.

Interview Questions and Answers

Q: Why should PDF parsing run in a Selenium task?

The task runs in Java, where filesystem and PDF parsing libraries fit naturally. The browser-side test keeps Selenium command flow and assertions, while the task returns a small serializable result. This separation also lets the task restrict paths and centralize parser lifecycle. I would unit test complex parsing logic outside the end-to-end suite.

Q: Is checking that the PDF file exists enough?

No. A stale, empty, truncated, HTML, unauthorized, or wrong document can exist at the expected path. I verify response contract, bytes, PDF signature, successful parsing, page structure, and business values. Visual or signature requirements need additional specialized checks.

Q: How do you avoid stale downloaded files?

I remove the expected file through a path-restricted task before the action or create a unique document and deterministic filename. In parallel runs, every worker receives unique data and artifact names. The test also waits for the current network response before reading the file.

Q: Why can extracted PDF text differ from what a user sees?

PDF content streams position glyphs rather than storing one canonical reading-order string. Columns, ligatures, hidden text, fonts, and drawing order can affect extraction. I normalize permitted whitespace and assert stable semantic facts. Layout gets a separate rendered-page check.

Q: When should you use an HTTP client instead of clicking Download?

I use an HTTP client for broad document-content combinations because it is faster and deterministic. I retain at least one UI download test to prove the control, request wiring, and filename behavior. The layers protect different contracts.

Q: How would you test a scanned PDF?

First I confirm that the requirement expects a text layer or scanned images. For image-only pages, I use an approved OCR pipeline with controlled languages, inputs, and confidence handling. I keep OCR assertions tolerant to its probabilistic nature and use visual or source-data checks as complementary evidence.

Q: How do you test a digitally signed PDF?

I use a signature-validation library or service that verifies cryptographic integrity, certificate trust, signing time, revocation policy, and allowed modifications. A visible signature image is not proof. Test identities and keys stay in protected infrastructure, and results avoid leaking document content.

Q: What should a PDF failure report include?

Include document type and synthetic identifier, request status, content type, sanitized disposition, byte length, parser result, page count, failed semantic assertion, environment version, and safe correlation data. Attach the document only when policy permits. Distinguish generation, download, parsing, content, and visual failures.

Common Mistakes

  • Calling a file-exists check complete PDF validation.
  • Parsing an old file left by an interactive or failed run.
  • Inventing a nonexistent built-in PDF parser or assuming Selenium has built-in PDF text extraction.
  • Calling the parser task before the current download is complete.
  • Comparing the entire extracted text despite unstable whitespace and reading order.
  • Using production logic as the only expected-value calculator.
  • Testing every PDF data combination through the browser UI.
  • Claiming text extraction proves visual layout, accessibility, signature, or PDF/A conformance.
  • Selecting the newest PDF from a shared folder during parallel execution.
  • Allowing a Java helper to read arbitrary filesystem paths.
  • Printing full documents, tokens, or personal data into CI logs.
  • Uploading sensitive failure artifacts without access and retention controls.

Conclusion

Selenium how to assert a downloaded PDF is solved reliably by layering evidence. Verify the response, wait for the new file with the filesystem helper, check its bytes, parse it in a restricted Java helper, and assert stable business facts. Add visual, OCR, signature, form, or conformance tools only when the requirement calls for them.

Implement the Apache PDFBox task first, then add one deterministic invoice or report test. Once it is stable, split broad content combinations into API-driven downloads and retain a small UI path. That design is faster, safer, and far easier to diagnose than a single file-exists assertion.

Interview Questions and Answers

Why parse PDFs in setupJavaEvents?

The task runs in Java with direct filesystem and parser-library access. Selenium retains command flow in the browser while the task returns a small JSON-safe result. The boundary also supports path validation and centralized resource cleanup.

What layers would you assert for a PDF download?

I assert authorization and response headers, current file creation, nontrivial bytes and PDF signature, parser success and page count, then stable business content. Visual, accessibility, form, conformance, and signature checks remain separate requirements.

How do you prevent a stale PDF false pass?

I remove the expected file safely before the action or create unique data and a deterministic filename. I observe the current request and isolate paths by worker. I never choose an arbitrary newest file from a shared directory.

Why is full extracted-text equality fragile?

PDF text items can have unstable whitespace and content-stream order even when rendering is unchanged. I normalize permitted whitespace and assert meaningful fields independently. Coordinate-aware or visual assertions cover structure where required.

When would you use an HTTP client for a PDF?

I use it for broad content and boundary coverage at the document endpoint. It gives direct headers and binary response and avoids repeated navigation. A smaller UI test still proves user-facing download wiring.

How would you validate an image-only PDF?

I first confirm the expected absence of a text layer, then use a controlled OCR pipeline if recognition is required. OCR output needs language and confidence policy. Visual and source-data assertions complement it.

How would you test PDF layout?

I render selected pages in a controlled environment with fixed fonts, data, locale, and producer version. Reviewed image baselines cover clipping and page breaks, while semantic assertions protect exact values. Baseline changes require intentional review.

What security controls belong in a PDF test task?

Resolve and restrict paths to the downloads directory, validate inputs, avoid logging passwords or content, return only needed fields, and destroy parser resources. Untrusted documents should be parsed in an appropriately isolated environment with maintained dependencies.

Frequently Asked Questions

Can Selenium read a downloaded PDF directly?

Selenium can read the file bytes with a Java filesystem read, but it does not include a built-in PDF text parser. Register a Java helper with a maintained library such as Apache PDFBox and return serializable text and page data.

Where does Selenium save downloaded files?

The default downloadsFolder is selenium/downloads unless the project changes it in configuration. Use the configured value consistently and keep generated files out of source control.

How do I wait for a PDF download in Selenium?

Observe the download request and use a filesystem wait on the expected path with an appropriate timeout. Its query and assertions retry, after which a Java helper can parse the completed file.

Why does PDF text extraction have strange spaces or order?

PDFs position text items on a page and do not always store one logical reading sequence. Normalize only allowed whitespace, assert stable facts, and use coordinate-aware or visual checks when table structure matters.

Should I download a PDF through the UI or API?

Use a UI test to prove the real download control and browser wiring. Use an HTTP client for broader document-content coverage because it is faster and gives direct access to response headers and bytes.

Can Selenium validate the visual layout of a PDF?

Not through text extraction alone. Render controlled pages with a suitable Java or CI tool and compare reviewed images, while retaining semantic assertions for values and identifiers.

How do I test an encrypted or signed PDF?

Pass protected test credentials through secure configuration to a parser that supports encryption. Use a dedicated cryptographic validator for signatures, because a visible signature image and successful text extraction do not prove integrity.

Related Guides