Overview

In web automation, a browser session in web automation represents a single browser instance, from connection to termination: closure, timeout, or disconnection, running in isolated environments to ensure resource exclusivity, thereby maintaining stability and performance.

These sessions are highly configurable through APIs, allowing for adjustments to settings such as running in a selected geographic region or specifying a keep alive session.

Sessions also support on-the-fly file downloads and can be easily started with automation frameworks like Playwright, Puppeteer, or Selenium, or pre-configured using a Session API, offering flexibility and control for developers.

Browser configuration

Sessions run on fast instances with isolated resources (storage, network, memory, and vCPUs).

The viewport, user agents, and header configuration are handled by the fingerprint mechanism.

Downloads are enabled and stored by default, accessible via the API.

Sessions

Starting a Session

A Session is either created implicitly upon connection (via connectOverCDP() or puppeteer.connect()), or via the Sessions API.

Once created, connect to a Session through a Driver (Playwright, Puppeteer, or Selenium) or via the Session Inspector.

You must connect to a Session within the timeout supplied during creation or the default timeout of your project.

Asynchronous Sessions

You can also create and manage Sessions asynchronously. This is useful if you want to run your automation in an asynchronous environment, such as an asyncio event loop.

Here’s an example using Playwright with async/await:

Playwright
import os
from playwright.async_api import async_playwright, Page
import asyncio

# Use environment variable for API key

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

async def run(browser_tab: Page):
    await browser_tab.goto("https://www.sfmoma.org")
    await browser_tab.get_by_role("link", name="Tickets").click()
    print(f"Current URL: {browser_tab.url} | Page title: {await browser_tab.title()}")

async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.connect_over_cdp(
            f"wss://connect.browserbase.com?apiKey={API_KEY}"
        )
        print(
            f"Connected to Browserbase. {browser.browser_type.name} version {browser.version}"
        )
        context = browser.contexts[0]
        browser_tab = context.pages[0]
        await run(browser_tab)

if __name__ == "__main__":
    asyncio.run(main())

Session Timeout

Sessions time out when running for longer than the timeout configured in your Project’s Settings:

The following code samples require the Browserbase SDK.

To keep sessions alive upon disconnections, provide the keepAlive param when creating a new Session and stop the session manually:

import Browserbase from "browserbase";

const BROWSERBASE_API_KEY = process.env.BROWSERBASE_API_KEY!;
const BROWSERBASE_PROJECT_ID = process.env.BROWSERBASE_PROJECT_ID!;

// Initialize the SDK
const bb = new Browserbase(BROWSERBASE_API_KEY);

// Create a session with `keepAlive` set to `true`
const session = await bb.sessions.create({
  projectId: BROWSERBASE_PROJECT_ID,
  keepAlive: true,
});

// Terminate the session
await bb.sessions.update(session.id, {
  projectId: BROWSERBASE_PROJECT_ID,
  status: "REQUEST_RELEASE",
});

For more information on using keep alive sessions, please refer to our Long Running Sessions guide.

We recommend that you release your keep alive sessions manually when no longer needed. They will time out eventually, but you may be charged for the unneeded browser minutes used.

Inspecting a Session

You can inspect a completed Session using the Session API or the Session Inspector:

ActionSession InspectorSessions API
Access logsSessions API logs endpoint
Access ChromeDevTools data (ex: network, DOM events)Sessions API logs endpoint
Access recordingSessions API recording endpoint
Retrieve downloaded filesSessions API downloads endpoint
Session Live ViewSessions API Live URLs endpoint
Access memory and CPUs usage

Session Concurrency and Rate Limiting

The number of concurrent browsers you can run depends on your plan:

PlanFreeHobbyStartupScale
Concurrent Browsers1350100+

Your concurrency means two things:

  1. You can have at most that many sessions running at the same time

  2. You can make at most that many requests to POST /v1/sessions in a minute

When reaching the session concurrency limit of your plan, any subsequent request to create a new session will return an HTTP 429 Too Many Requests error. That means the request was effectively dropped. To check the status of your rate limit, you can look at the headers of the response:

  • x-ratelimit-limit - How many requests you can make.

  • x-ratelimit-remaining - How many requests remain in the time window.

  • x-ratelimit-reset - How many seconds must pass before the rate limit resets.

  • retry-after - If the max has been reached, this is the number of seconds you must wait before you can make another request. This is documented here.

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
x-ratelimit-limit: 3
x-ratelimit-remaining: 0
x-ratelimit-reset: 45
retry-after: 45

To avoid rate limits, you can either by run fewer concurrent sessions or close sessions explicitly as opposed to letting them time out.

For example, if you have a Hobby plan with a limit of 3 concurrent sessions, you can create up to 3 sessions in a 60 second window. If you try to create a 4th session within that window, it will be rate limited and return an HTTP 429 error.

If you need more concurrency, you can upgrade to a plan that allows for a higher limit. For example, the Hobby plan allows for 3 concurrent browsers while the Startup plan increases the limit to 50. The Scale plan is customizable to the amount of concurrency that you require. If you are interested in upgrading you plan, please reach out to: support@browserbase.com

User Metadata

Our List Sessions endpoint supports filtering sessions by status. This is helpful but not highly configurable. User metadata allows you to attach arbitrary JSON data to sessions, which then gives you additional flexibility when querying sessions.

Attaching User Metadata to a Session

User metadata is attached to a session when hitting our Create Session endpoint. This metadata can be any JSON-serializable object.

This metadata is attached to the stored session object and can be queried against using the List Sessions endpoint.

Below is an example for attaching an order status to a created session. This will attach the object {"order": {"status": "shipped"}} to the created session.

curl --request POST \
  --url "https://api.browserbase.com/v1/sessions" \
  --header 'Content-Type: application/json' \
  --header 'X-BB-API-Key: <api-key>' \
  --data '{"projectId": "<project-id>", "userMetadata": {"order": {"status": "shipped"}}}'

The size of the stored JSON object is limited to 512 characters. We measure this by converting your object into a JSON string (think JSON.stringify) and measuring the length of the resulting string.

Querying Sessions by User Metadata

Querying using user metadata is done via the q query parameter on the List Sessions endpoint.

Let’s use the example object {"order": {"status": "shipped"}} from the previous section. To query for all sessions with an order of status "shipped", you can use the following query:

user_metadata['order']['status']:'shipped'

This query contains the following components:

  • user_metadata is known as the “base” of the query. Currently we only support the user_metadata base, although we’re working to support more querying bases in the future. Stay tuned!

  • ['order']['path'] is known as the “path” of the query. The path is used to drill into nested fields in the stored metadata object. In this case, we’re looking for an object with keys in the shape { "order": { "status" }}.

  • 'shipped' is known as the “value” of the query. This is separated from the base and the path of the query with a : character. The “value” field of the query is used to check strict equality of the value specified by the “path” of the query. In our case, we’re looking for an object with the exact shape { "order": { "status": "shipped" }}.

Note that we need to URL encode the query string to ensure that it’s properly parsed by the API.

  • %5B is the URL encoded version of [

  • %5D is the URL encoded version of ]

  • %3A is the URL encoded version of :

In JavaScript, you can use encodeURIComponent("user_metadata['order']['status']:'shipped'") to encode the query string.

Below is an example of how to use this query.\

curl --request GET \
  --url "https://api.browserbase.com/v1/sessions?q=user_metadata%5B'order'%5D%5B'status'%5D%3A'shipped'" \
  --header 'X-BB-API-Key: <api-key>'

This will return a list of all sessions with attached metadata in the form {"order": {"status": "shipped"}}. If the query doesn’t match any sessions, the API will respond with an empty list [].

Currently we only support querying by fields (no arrays) and checking value equality of string (no numbers or booleans). A quick workaround for this is to convert numbers and booleans into strings and query normally. Stay tuned!