> ## 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.

# Uploads

Upload files to websites using Playwright, Puppeteer, or Selenium. The approach varies by framework:

## Playwright

### Direct upload

With Playwright, upload files directly from your local path. After [creating and connecting to a session](/platform/browser/getting-started/using-browser-session), follow these steps:

1. Make sure your file is available where you're running your Playwright code
2. Use the `setInputFiles` method to upload the file
3. The file path should be relative to your current working directory

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

    (async () => {
      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];

      await page.goto("https://browser-tests-alpha.vercel.app/api/upload-test");

      const fileInput = page.locator("#fileUpload");
      // logo.png is available relative to the current working directory
      await fileInput.setInputFiles("logo.png");
    })().catch((error) => console.error(error));
    ```
  </Tab>

  <Tab title="Python">
    ```Python Playwright theme={null}
    from playwright.sync_api import sync_playwright
    from browserbase import Browserbase
    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]

        page.goto("https://browser-tests-alpha.vercel.app/api/upload-test")

        file_input = page.locator("#fileUpload")
        file_input.set_input_files("logo.png")
    ```
  </Tab>
</Tabs>

### Large file uploads

For larger files, use the [Session Uploads API](/reference/api/create-session-uploads):

<Tabs>
  <Tab title="Node.js">
    <CodeGroup>
      ```typescript Playwright theme={null}
      // IMPORTANT: Set your file name below
      const fileName = "YOUR_FILE_NAME.EXAMPLE";

      import { chromium } from "playwright-core";
      import { Browserbase } from "@browserbasehq/sdk";
      import * as fs from "fs";

      const apiKey = process.env.BROWSERBASE_API_KEY!;

      async function upload() {
        // 1. Initialize Browserbase Client
        console.log("Initializing Browserbase client");
        const bb = new Browserbase({ apiKey });

        // 2. Create Browser Session
        console.log("Creating new browser session");
        const session = await bb.sessions.create();

        // 3. Upload file via the Uploads API
        console.log("Uploading file");
        try {
          const fileStream = fs.createReadStream(fileName);
          const result = await bb.sessions.uploads.create(session.id, {
            file: fileStream,
          });
          console.log(`Upload successful: ${JSON.stringify(result)}`);
        } catch (error) {
          console.error(`Upload failed... exiting: ${error}`);
          return;
        }

        // 4. Connect to the Session
        console.log("Connecting to browser session");
        const browser = await chromium.connectOverCDP(session.connectUrl);
        const defaultContext = browser.contexts()[0];
        const page = defaultContext.pages()[0];

        // 5. Get Live View link for remote debugging
        const liveViews = await bb.sessions.debug(session.id);
        console.log("Live View link:", liveViews.debuggerUrl);

        // 6. Use the Browser
        console.log("Navigating to page: upload-test");
        await page.goto("https://browser-tests-alpha.vercel.app/api/upload-test", {
          waitUntil: "domcontentloaded",
        });

        // Set up CDP client for additional controls
        const cdpSession = await defaultContext.newCDPSession(page);
        const root = await cdpSession.send("DOM.getDocument");

        // Find the input element
        const inputNode = await cdpSession.send("DOM.querySelector", {
          nodeId: root.root.nodeId,
          selector: "#fileUpload",
        });

        // Use DOM.setFileInputFiles CDP command
        const remoteFilePath = `/tmp/.uploads/${fileName}`;
        await cdpSession.send("DOM.setFileInputFiles", {
          files: [remoteFilePath],
          nodeId: inputNode.nodeId,
        });

        console.log("Waiting for 60 seconds: allow time for 1) file upload and 2) to see the file upload...");
        await new Promise((resolve) => setTimeout(resolve, 60000));

        // 7. Cleanup
        console.log("Closing browser session");
        await page.close();
        await browser.close();

        // 8. Session Recording Link
        console.log(`
      Your session dashboard is ready:
        https://www.browserbase.com/sessions/${session.id}`);
      }

      // Execute the main function
      upload().catch((error) => console.error(error));

      ```
    </CodeGroup>
  </Tab>

  <Tab title="Python">
    <CodeGroup>
      ```python Playwright theme={null}
      # IMPORTANT: Set your file name below
      file_name = "YOUR_FILE_NAME.EXAMPLE"

      import os
      from browserbase import Browserbase
      from playwright.sync_api import sync_playwright
      import time

      api_key = os.environ.get("BROWSERBASE_API_KEY")

      def upload(playwright):
        # 1. Initialize Browserbase Client
        print("Initializing Browserbase client")
        bb = Browserbase(api_key=api_key)

        # 2. Create Browser Session
        print("Creating new browser session")
        session = bb.sessions.create()

        # 3. Upload file via the Uploads API: https://docs.browserbase.com/reference/api/create-session-uploads
        print("Uploading file")
        try:
          with open(file_name, 'rb') as file:
            result = bb.sessions.uploads.create(
              id=session.id,
              file=file
          )
            print(f"Upload successful: {result}")
        except Exception as e:
          print(f"Upload failed... exiting: {str(e)}")
          return

        # 4. Connect to the Session
        print("Connecting to browser session")
        browser = playwright.chromium.connect_over_cdp(session.connect_url)
        default_context = browser.contexts[0]
        page = default_context.pages[0]

        # 5. Get Live View link for remote debugging
        live_views = bb.sessions.debug(session.id)
        print("Live View link:", live_views.debugger_url)

        # 6. Use the Browser
        print("Navigating to page: upload-test")
        page.goto("https://browser-tests-alpha.vercel.app/api/upload-test", wait_until="domcontentloaded")

        # Set up CDP client for additional controls
        cdp_session = default_context.new_cdp_session(page)

        root = cdp_session.send('DOM.getDocument')

        # Find the input element
        input_node = cdp_session.send('DOM.querySelector', {
          'nodeId': root['root']['nodeId'],
          'selector': '#fileUpload'
        })

        # Use DOM.setFileInputFiles CDP command with the found nodeId and set the remote file path
        remote_file_path = f"/tmp/.uploads/{file_name}";
        cdp_session.send('DOM.setFileInputFiles', {
          'files': [remote_file_path],
          'nodeId': input_node['nodeId']
        })

        print("Waiting for 60 seconds: allow time for 1) file upload and 2) to see the file upload...")
        time.sleep(60)

        # 7. Cleanup
        print("Closing browser session")
        page.close()
        browser.close()

        # 8. Session Recording Link
        print(f"""
      Your session dashboard is ready:
        https://www.browserbase.com/sessions/{session.id}""")

      # Execute the main function
      if __name__ == "__main__":
          with sync_playwright() as playwright:
              upload(playwright)
      ```
    </CodeGroup>
  </Tab>
</Tabs>

### Manual upload through Live View

When using [Live View](/platform/browser/observability/session-live-view), clicking a file input triggers the browser's native file picker. Since the browser runs remotely on Browserbase infrastructure, it can't access files on your local machine.

To handle manual uploads through Live View, intercept file chooser events and upload programmatically:

1. Detect file input clicks using Playwright's `page.on('filechooser')` event
2. Show your own file picker (e.g., a native OS picker or web UI) to select a local file
3. Upload the file via the Session Uploads API
4. Attach the file to the input element using CDP's `DOM.setFileInputFiles`

See the following [example script](https://github.com/browserbase/playbook/blob/main/node/playwright/_tools/uploads/live-view-upload.ts) for a complete implementation.

<Card title="Session uploads API" icon="server" iconType="sharp-solid" href="/reference/api/create-session-uploads">
  Learn more about the available params and response fields
</Card>
