> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browserbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dialogs

> Handling browser dialog windows in automated sessions.

## What are Chrome dialogs?

A Chrome dialog is any pop-up or modal window that Google Chrome itself creates (not part of a web page) to communicate something to the user or request input. These include:

* **`alert()`** dialogs that display a message with an "OK" button
* **`confirm()`** dialogs that ask for confirmation with "OK" and "Cancel" buttons
* **`prompt()`** dialogs that request text input from the user
* **`window.print()`** dialogs that open the browser's print interface

These native browser dialogs are different from custom web page modals and require special handling in automation.

## Why you can't interact with them directly

Chrome dialogs block JavaScript execution on the page until they're dismissed. This means:

* Automation tools can't interact with the page while a dialog is open
* Automation scripts will hang until the dialog is manually dismissed

## Preventing Chrome dialogs

The best approach is to prevent these dialogs from appearing by overriding the native dialog functions before any page code runs. Use `addInitScript()`, which executes code before any page scripts.

### Implementation

<Tabs>
  <Tab title="Node.js">
    ```javascript Playwright theme={null}
    import { chromium } from "playwright-core";
    import { Browserbase } from "@browserbasehq/sdk";

    const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
    const session = await bb.sessions.create();

    const browser = await chromium.connectOverCDP(session.connectUrl);
    const defaultContext = browser.contexts()[0];
    const page = defaultContext.pages()[0];

    // Override dialog functions before page loads
    await page.context().addInitScript(() => {
      window.alert = () => {};
      window.confirm = () => true;
      window.prompt = () => '';
    });

    // Now navigate to your target page
    await page.goto("https://example.com");

    // Dialogs should now be prevented

    await page.close();
    await browser.close();
    ```
  </Tab>

  <Tab title="Python">
    ```python Playwright theme={null}
    from browserbase import Browserbase
    from playwright.sync_api import sync_playwright
    import os

    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
    session = bb.sessions.create()

    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp(session.connect_url)
        context = browser.contexts[0]
        page = context.pages[0]

        # Override dialog functions before page loads
        context.add_init_script("""
            window.alert = () => {};
            window.confirm = () => true;
            window.prompt = () => '';
        """)

        # Now navigate to your target page
        page.goto("https://example.com")

        # Dialogs should now be prevented

        page.close()
        browser.close()
    ```
  </Tab>
</Tabs>

### Customizing dialog behavior

You can customize the return values based on your automation needs:

```javascript theme={null}
// Always reject confirmations
window.confirm = () => false;

// Return a specific value for prompts
window.prompt = () => 'my custom input';

// Log when dialogs would have appeared
window.alert = (message) => console.log('Alert prevented:', message);
```

## Handling PDF dialogs

PDF dialogs present unique challenges because PDFs can be generated and displayed in different ways. You'll encounter two common scenarios:

### Scenario 1: PDF opens in the current tab

When a PDF replaces the current page content, you need to capture it differently:

<Tabs>
  <Tab title="Node.js">
    ```javascript Playwright theme={null}
    import { chromium } from "playwright-core";
    import { Browserbase } from "@browserbasehq/sdk";
    import fs from 'fs/promises';

    const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
    const session = await bb.sessions.create();

    const browser = await chromium.connectOverCDP(session.connectUrl);
    const context = browser.contexts()[0];
    const page = context.pages()[0];

    let savedPdfPath: string | null = null;

    // Route PDF requests to capture them
    await context.route('**/*.pdf', async (route) => {
      const resp = await route.fetch();
      const contentType = (resp.headers()['content-type'] ?? '').toLowerCase();

      if (contentType.includes('application/pdf')) {
        const url = route.request().url();
        const name = new URL(url).pathname.split('/').pop() || 'document.pdf';
        const outputPath = `captured-${Date.now()}-${name}`;
        const buffer = await resp.body();

        await fs.writeFile(outputPath, buffer);
        console.log('Saved PDF (network):', outputPath, 'from', url);
        savedPdfPath = outputPath;
      }

      await route.fulfill({ response: resp });
    });

    // Override print dialog
    await context.addInitScript(() => {
      window.print = () => {};

      // Also capture client-side blobs as fallback
      const origCreate = URL.createObjectURL;
      (window as any).__pdfBlobs = [];
      URL.createObjectURL = function (blob: Blob) {
        try {
          if ((blob as any)?.type?.toLowerCase?.().includes('application/pdf')) {
            (window as any).__pdfBlobs.push(blob);
          }
        } catch {}
        return origCreate.apply(this, arguments);
      };
    });

    await page.goto("https://dialogue-interaction.vercel.app/");

    // Trigger PDF generation
    await page.click("#open-pdf");

    // If network capture didn't work, try blob capture
    if (!savedPdfPath) {
      const arrays = await page.evaluate(async () => {
        const blobs: Blob[] = (window as any).__pdfBlobs || [];
        const bufs = await Promise.all(blobs.map(b => b.arrayBuffer()));
        return bufs.map(ab => Array.from(new Uint8Array(ab)));
      });

      if (arrays.length) {
        const buf = Buffer.from(Uint8Array.from(arrays[0]));
        const outputPath = `captured-blob-${Date.now()}.pdf`;
        await fs.writeFile(outputPath, buf);
        console.log('Saved PDF (blob):', outputPath);
        savedPdfPath = outputPath;
      }
    }

    await page.close();
    await browser.close();
    ```
  </Tab>

  <Tab title="Python">
    ```python Playwright theme={null}
    from playwright.sync_api import sync_playwright
    from browserbase import Browserbase
    import time
    import os

    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
    session = bb.sessions.create()

    saved_pdf_path = None

    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp(session.connect_url)
        context = browser.contexts[0]
        page = context.pages[0]

        # Route PDF requests to capture them
        def handle_route(route):
            nonlocal saved_pdf_path
            response = route.fetch()
            content_type = (response.headers.get('content-type', '')).lower()

            if 'application/pdf' in content_type:
                url = route.request.url
                name = url.split('/')[-1] or 'document.pdf'
                output_path = f"captured-{int(time.time() * 1000)}-{name}"
                buffer = response.body()

                with open(output_path, 'wb') as f:
                    f.write(buffer)
                print(f"Saved PDF (network): {output_path} from {url}")
                saved_pdf_path = output_path

            route.fulfill(response=response)

        context.route('**/*.pdf', handle_route)

        # Override print dialog and capture blobs
        context.add_init_script("""
            window.print = () => {};

            const origCreate = URL.createObjectURL;
            window.__pdfBlobs = [];
            URL.createObjectURL = function(blob) {
                try {
                    if (blob?.type?.toLowerCase?.().includes('application/pdf')) {
                        window.__pdfBlobs.push(blob);
                    }
                } catch {}
                return origCreate.apply(this, arguments);
            };
        """)

        page.goto("https://dialogue-interaction.vercel.app/")

        # Trigger PDF generation
        page.click("#open-pdf")

        # If network capture didn't work, try blob capture
        if not saved_pdf_path:
            arrays = page.evaluate("""
                async () => {
                    const blobs = window.__pdfBlobs || [];
                    const bufs = await Promise.all(blobs.map(b => b.arrayBuffer()));
                    return bufs.map(ab => Array.from(new Uint8Array(ab)));
                }
            """)

            if arrays:
                pdf_data = bytes(arrays[0])
                output_path = f"captured-blob-{int(time.time() * 1000)}.pdf"
                with open(output_path, 'wb') as f:
                    f.write(pdf_data)
                print(f"Saved PDF (blob): {output_path}")
                saved_pdf_path = output_path

        browser.close()
    ```
  </Tab>
</Tabs>

### Scenario 2: PDF opens in a new tab

When a PDF is generated client-side and opens in a new tab, you can capture the PDF blob before it's displayed:

<Tabs>
  <Tab title="Node.js">
    ```javascript Playwright theme={null}
    import { chromium } from "playwright-core";
    import { Browserbase } from "@browserbasehq/sdk";
    import fs from 'fs/promises';

    const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
    const session = await bb.sessions.create();

    const browser = await chromium.connectOverCDP(session.connectUrl);
    const context = browser.contexts()[0];
    const page = context.pages()[0];

    // Prevent print dialog and capture PDF blobs
    await context.addInitScript(() => {
      // Don't let native print dialog block
      window.print = () => {};

      // Capture client-side generated PDF blobs
      const origCreate = URL.createObjectURL;
      (window as any).__pdfBlobs = [];
      URL.createObjectURL = function (blob: Blob) {
        try {
          if ((blob as any)?.type?.toLowerCase?.().includes('application/pdf')) {
            (window as any).__pdfBlobs.push(blob);
          }
        } catch {}
        return origCreate.apply(this, arguments);
      };
    });

    await page.goto("http://pdfmake.org/playground.html");

    // Trigger PDF generation by clicking the print button
    await page.click("#printThis li:nth-child(2)");

    // Wait for PDF to be generated
    await page.waitForTimeout(1000);

    // Extract and save the PDF
    const arrays = await page.evaluate(async () => {
      const blobs: Blob[] = (window as any).__pdfBlobs || [];
      const bufs = await Promise.all(blobs.map(b => b.arrayBuffer()));
      return bufs.map(ab => Array.from(new Uint8Array(ab)));
    });

    if (arrays.length) {
      const buf = Buffer.from(Uint8Array.from(arrays[0]));
      const outputPath = `captured-blob-${Date.now()}.pdf`;
      await fs.writeFile(outputPath, buf);
      console.log('Saved PDF (blob):', outputPath);
    }

    await page.close();
    await browser.close();
    ```
  </Tab>

  <Tab title="Python">
    ```python Playwright theme={null}
    from playwright.sync_api import sync_playwright
    from browserbase import Browserbase
    import time
    import os

    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
    session = bb.sessions.create()

    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp(session.connect_url)
        context = browser.contexts[0]
        page = context.pages[0]

        # Prevent print dialog and capture PDF blobs
        context.add_init_script("""
            window.print = () => {};

            const origCreate = URL.createObjectURL;
            window.__pdfBlobs = [];
            URL.createObjectURL = function(blob) {
                try {
                    if (blob?.type?.toLowerCase?.().includes('application/pdf')) {
                        window.__pdfBlobs.push(blob);
                    }
                } catch {}
                return origCreate.apply(this, arguments);
            };
        """)

        page.goto("http://pdfmake.org/playground.html")

        # Trigger PDF generation by clicking the print button
        page.click("#printThis li:nth-child(2)")
        page.wait_for_timeout(1000)

        # Extract and save the PDF
        arrays = page.evaluate("""
            async () => {
                const blobs = window.__pdfBlobs || [];
                const bufs = await Promise.all(blobs.map(b => b.arrayBuffer()));
                return bufs.map(ab => Array.from(new Uint8Array(ab)));
            }
        """)

        if arrays:
            pdf_data = bytes(arrays[0])
            output_path = f"captured-blob-{int(time.time() * 1000)}.pdf"
            with open(output_path, 'wb') as f:
                f.write(pdf_data)
            print(f"Saved PDF (blob): {output_path}")

        browser.close()
    ```
  </Tab>
</Tabs>

### How PDF capture works

Both scenarios use a combination of techniques:

1. **Override `window.print()`** - Prevents the native print dialog from blocking automation
2. **Intercept `URL.createObjectURL()`** - Captures client-side generated PDF blobs before they're displayed
3. **Route network requests** (Scenario 1) - Intercepts PDF files loaded from the network

The key difference:

* **Scenario 1**: PDF might be fetched from the network or generated, and the print dialog appears in the current tab
* **Scenario 2**: PDF is generated client-side and stored in a blob, opened in a new tab where the print dialog appears
