import ScreenshotGallery from "../../components/ScreenshotGallery.astro";
import StoreCta from "../../components/StoreCta.astro";
import pdfResults from "../../assets/screenshots/article-pdf-reports.png";

To download PDFs from multiple web pages in Chrome, use **For Each Link** in [Tab Automation](/) to visit the pages, **Save Value → Link address** to read each document link, and **Download File** to save its destination. Check for the link before running those last two steps. When the pass finishes, inspect the saved documents and export a ZIP.

This recipe is for a report library or product catalog where each detail page has one PDF link in the same place. You configure that link once and reuse the selection across the page list. The PDFs already exist on the website; this workflow does not print web pages to PDF or discover every document across a domain.

## Check how the website provides its PDFs

Use the website's own bulk export if it supplies the documents you need. For a few files, Chrome's [Save Link As option](https://support.google.com/chrome/answer/95759?hl=en) may be enough.

For this automation, start with two or three detail pages you can open normally. On each page, check that the chosen link leads to the expected PDF. The same link selection must work on every page: a manual, invoice, and brochure in different positions need more configuration than this example.

A button that generates a file through a form, a `blob:` address, or a viewer without an accessible HTTP(S) document link does not fit this recipe. A file address may end in something other than `.pdf`; inspect the document it returns instead of judging only the suffix.

If the files themselves are already linked together on one page, a dedicated bulk downloader can be simpler. The steps below address a list of **web pages that each contain a document link**. Do not paste PDF addresses into this page list and expect the automation to find a link inside the PDF viewer.

## See a verified three-PDF export

We ran an unpacked test build of Tab Automation 1.0.0 against four internal **Fieldwork report pages**. These pages and their one-page PDFs contain controlled demo data, not real organizational reports.

| Page visited    | Result                                        |
| --------------- | --------------------------------------------- |
| Studio report   | Saved `studio.pdf`, reference ST-101          |
| Pending report  | No document link; skipped the download branch |
| Workshop report | Saved `workshops.pdf`, reference WS-202       |
| Visit report    | Saved `visit.pdf`, reference VI-303           |

The pass used a pasted URL list, **Wait / Delay → Fixed → 5 seconds**, then **If / Else** with Save Value and Download File inside **Then**. **Else** was empty. **Repeat** was off and **Skip visited** was **Never**. We made a separate Test download first and excluded it from the batch export.

The missing link was deliberately placed after a successful save. The batch retained exactly three documents, and every PDF in the exported ZIP matched its original file byte for byte. The missing page did not trigger a second download of the previous report.

<ScreenshotGallery
  landscape
  shots={[
    {
      image: pdfResults,
      title: "Three reports from four pages",
      caption:
        "Actual Dashboard output from the controlled demo. Open the full-size screenshot to inspect the files.",
      alt: "Tab Automation Dashboard showing studio.pdf, workshops.pdf, and visit.pdf retained by the Fieldwork PDF reports run.",
    },
  ]}
/>

[Download the actual three-PDF ZIP](/samples/guides/fieldwork-pdf-reports.zip). It also includes the exporter's manifest with source information. The source-page addresses visible in the Dashboard belong to our local test server; they are not public practice pages.

<StoreCta fallback="/#how-it-works" showNote={false} placement="guide-demo" />

## Test one PDF link first

Use desktop Chrome with Tab Automation installed. Custom automations are free. [Explorer access](/blog/launch-license) unlocks the full Dashboard shown here; the basic saved-results list also provides exports.

1. Open a detail page with a working PDF link. Sign in yourself first if the site requires it.
2. Open the side panel and choose **New Automation**. Under **Tab & Startup**, turn off **Run in a new tab**, select that tab, and leave **Start when browser opens** off for this manually started collection.
3. Expand [Values](/steps/values), add the name `pdf_url`, and leave its starter text empty.
4. Add [Save Value](/steps/save-value). Choose **Link address**, select `pdf_url` under **Save as**, and use **Pick element to save** on the PDF link. The CSS selector identifies the element to read on each page.
5. Choose **Test save** and check the confirmation. It shows only the beginning of the sampled value; it does not write the live Value used by a running automation.
6. On the web page, right-click that same PDF link and choose **Copy link address** to obtain its complete URL. Add [Download File](/steps/download-file), paste the literal HTTP(S) address, and choose **Test download**. Open **Dashboard → Saved results**, find the Test file, download it, and open it to confirm its contents.

Testing Save Value and then testing `{{pdf_url}}` as two separate editor actions does not pass the sample between them. Use the literal address for this single-file test. The running sequence below saves and uses the Value in order.

## Collect the page URLs and configure the download branch

Create a fresh automation for the batch so the single-page test steps are not accidentally left outside Each Link. Name it something recognizable, such as `Fieldwork PDF reports`. Select the same tab under **Tab & Startup**, with **Run in a new tab** and **Start when browser opens** off, and declare `pdf_url` under Values again.

1. Add [For Each Link](/steps/for-each-link), choose **Paste list**, and enter the detail-page URLs, one complete HTTP(S) URL per line. Start with a fresh loop without a picked link selector; live selector matches take priority over a pasted list.
2. Inside **Each Link**, add **Wait / Delay → Fixed → 5 seconds**. Adjust this for your pages. A fixed wait gives content time to load but does not establish that the document link is ready.
3. Use **Go To This Link → Open** beside a sample URL to configure the steps on that page.
4. After the wait, add [If / Else](/steps/if-else). Use **Pick on page** to select the document link and set the Page check to **Exists**. In **CSS Selector**, restrict the selection to an anchor with a nonempty `href`.
5. Inside **Then**, add **Save Value → Link address**, select `pdf_url`, and use the **same CSS selector** as the condition. Add **Download File** immediately after it, also inside Then, with `{{pdf_url}}` as its URL. Leave **Else** empty.
6. Open a second page with **Go To This Link → Open**. Use **Test condition** and **Test save** to check the match and the start of the sampled value. Copy and test the full link address separately as above. Check any different page layouts before running them together.
7. Set **Skip visited → Never** for this deliberate collection. Turn **Repeat** off in the End block for one pass, then choose **Save & Run**.

Our demo's condition and Save Value both use `a.report-pdf[href]:not([href=""])`. Here `a.report-pdf` identifies the site's report anchor; the remaining part requires a nonempty link address. Replace the site-specific part with the selector for your actual PDF link. This selector does not detect PDFs by content or validate the destination's protocol; inspect the sampled HTTP(S) addresses before the batch.

Keep Chrome open and leave the assigned tab to the automation. For Each Link visits the pages sequentially in that tab. It does not open a parallel download queue or automatically follow pagination. For collecting a longer page list, see the [link-walking guide](/blog/walk-through-links-in-chrome).

## Why the link check matters

**Save Value keeps its previous contents if a later capture fails.** A missing element or missing link address produces a warning, and later steps can still run. Without the condition, Download File could receive the previous page's `pdf_url` again.

Putting both steps inside Then skips them when the link is absent at the condition check. The empty Else continues to the next page. This is a current-page check, not a guarantee against a page changing between the check and Save Value. Inspect Activity warnings and the saved documents even when the run completes.

If a link appears late, increase the wait and test again. If its layout differs, correct the selection or collect those pages separately. Do not interpret a skipped page as proof that no PDF exists anywhere on it.

## Inspect the documents and export a ZIP

After the pass finishes, open **Dashboard → Saved results** and find the files from your batch. Check their source-page addresses and compare the saved count with the pages that actually had document links. Keep the earlier Test result separate.

Download and open the PDFs to check their titles, contents, and versions. A successful fetch can save a login or error page if that is what the URL returns; a `.pdf` filename and a completed run do not prove that the document is correct.

Select the batch's file rows and choose **Export… → ZIP → Export**. Saving files during the run retains them in extension-owned local storage; this explicit export creates the download. An individual file can also be downloaded on its own. Results remain until you delete them; uninstalling the extension or clearing its storage removes them.

## Recover missing or incorrect files

Pause an active collection before changing its setup. Review **Activity** warnings and open the affected detail page yourself. Check the selected link, the current account, and whether the expected document is available.

If access expired, sign in again manually and repeat the single-file test. Collect only the affected page URLs in a fresh short batch, then inspect and export those results separately. Reading a link from your signed-in page does not guarantee the separate file request will authenticate successfully on every site.

Download File accepts HTTP(S) addresses, follows redirects, and supports files up to 1,000,000,000 bytes each. It does not provide custom request headers or a POST body. A storage failure pauses the affected save for retry; network or size failures report a failed step. Review the output rather than assuming every page supplied a document.

For a new collection, check a sample again, keep Repeat off, and use Skip visited → Never when revisiting the same pages. If the job is instead to keep versions of one changing file, follow [automatically downloading a file on an interval](/blog/automatically-download-file-chrome).
