Misc

Downloading Files - Click to Save Without a Dialog

Three Download Paths

Dialog mode (WithPromptForDownload(true)) waits for the OS Save As window to appear, then uses hardware emulation to type the target filename into it and press Enter -- no mouse needed, no manual interaction. Silent mode (the default) clicks the element and watches the filesystem for a new file of the matching extension in the browser default download directory, then moves it to the path you specified. Direct mode (WithUseDirectDownload(true)) bypasses the browser download mechanism and fetches the file via WebClient using the href or src attribute of the clicked element -- useful when the browser would show a dialog or open the file inline instead of saving it. Note that WebClient does not carry the active browser user agent, so sites that gate downloads on UA matching may reject it.

// Path 1 - Dialog: wait for OS Save As window,

// type filename via hardware, press Enter:

GPAL.Browser

.WithPromptForDownload(true)

.GoTo("https://example.com/reports")

.WithSelector(downloadBtn)

.LeftClickAndDownload(

GPAL.FileFor(@"C:Reports eport.csv"))

.Close();


// Path 2 - Silent: click, watch default

// download dir, move file when it appears:

// (default - WithPromptForDownload(false))


// Path 3 - Direct: bypass the browser entirely,

// fetch via websocket:

GPAL.Browser

.WithUseDirectDownload(true)

.GoTo("https://example.com/data")

.WithSelector(linkSel)

.LeftClickAndDownload(

GPAL.FileFor(@"C:Dataexport.xlsx"))

.Close();

NOTE

All three paths wait up to WithDownloadTimeoutInSec(int) seconds for the file to arrive before logging an error and continuing. Default is 60 seconds. Increase it for large files or slow connections.

Dialog Mode - Hardware Fills In the Save As Window

When the Save As dialog opens, GPAL calls HardwareHelper.SendString with the target filename, then SendKey(VK_RETURN). If the dialog is still present after the first Enter (some browsers need two), it sends Enter again. GPAL then waits for the file to fully write to disk before returning. This path requires the browser to be running in headed mode -- it cannot work headless because the OS dialog has nowhere to render.

GPAL.Browser

.WithPromptForDownload(true)

.WithDownloadTimeoutInSec(120)

.GoTo("https://example.com")

.WithSelector(exportBtn)

.LeftClickAndDownload(

GPAL.FileFor(@"C:Exportsdata.zip"))

.Close();


// Chrome/Edge waits for: "Save As"

// Firefox waits for: "Enter name of file

// to save to..."

NOTE

Some sites show a consent or confirmation modal between the click and the actual download starting. Define those as persistent selectors and GPAL will automatically dismiss them before waiting for the Save As dialog.

Silent Mode, Headless, and Per-Engine Behavior

In silent mode, each engine handles the download in its own way. Selenium in headed mode sets up a filesystem watcher on the default download directory, clicks the element, waits for a file with the matching extension to land, then moves it to your target path. Selenium in headless mode uses CDP Page.setDownloadBehavior to route the file directly to the target location without a dialog or watcher. OttoMagic intercepts the download natively inside the Chrome extension and routes the file to the target path without any OS dialog involvement. Puppeteer uses its own built-in download handling to intercept the response and write the file directly. In every case the call is identical -- WithPromptForDownload and WithUseDirectDownload apply consistently and GPAL selects the correct internal path for the active engine automatically.

// Silent mode -- what each engine does internally:

//

// Selenium (headed): sets up a filesystem watcher

// on the default download directory, clicks,

// waits for a new file, moves it to target path.

//

// Selenium (headless): CDP Page.setDownloadBehavior

// routes the file directly to the target location

// -- no dialog, no watcher needed.

//

// OttoMagic: native download intercept inside

// the Chrome extension routes the file directly

// to the target path without OS involvement.

//

// Puppeteer: built-in Puppeteer download handling

// intercepts the response and writes the file

// to the target path directly.

//

// Same LeftClickAndDownload call in all cases.

// GPAL selects the correct engine path for you.

NOTE

When a click produces no downloaded file but the browser navigates to a new URL, GPAL checks automatically whether that URL is a PDF -- first by looking for a .pdf extension, then by issuing an HttpClient HEAD request and inspecting the Content-Type and Content-Disposition response headers. If a PDF is confirmed, GPAL checks the target directory and the default download directory in case the browser already placed it there, and moves it into position. If it is not there, GPAL downloads it directly via HttpClient -- using the live user agent queried from the active engine so the out-of-band request presents the same identity as the browser session.

💬 Ask GPAL