Skip to main content

What is a serverless browser function?

What is a serverless browser function?
Lucas Giordano's avatarBy Lucas Giordano · Co-founder, Notte
Last updated
TL;DR

A serverless browser function is your handler code packaged with a per-invocation cloud browser session and deployed as a callable HTTP endpoint. Invoke it, a fresh browser spins up, your code runs, the result comes back, the browser tears down. The unit primitive of Notte's Anything API and the right shape for any browser-driven work that should be callable from elsewhere — agents, scheduled jobs, integrations.

What is a serverless browser function?

A regular AWS Lambda runs your code on demand without you managing servers. A serverless browser function does the same thing with a real Chromium attached to every invocation. You write the handler — a Python function that uses a browser session to do whatever browser work is needed — and the platform makes it deployable, callable, scalable, and billable per invocation. The shape clicks immediately for anyone who's used Lambda; the difference is the browser, and that's the whole point.

What you're getting in one primitive

A serverless browser function bundles four things into one deployment:

  • Handler code. Your Python file with a run(...) function as the entry point. Inside it you open a session, drive an agent, extract data, return a result.
  • A fresh browser per invocation. Each call gets its own serverless browser session — clean state, fresh fingerprint, optional residential proxy.
  • A callable HTTP endpoint. The function gets a stable URL or function ID. Any system that can make an HTTP request can invoke it.
  • The full operations layer. Cold-start handling, retry on failure, observability per invocation, structured logs, optional scheduling.

You write the handler. The platform handles everything else.

The Notte SDK shape

main.py
# acme_invoices.py — the function handler
from notte_sdk import NotteClient

client = NotteClient()

def run(account_id: str, days_back: int = 30):
    with client.Session(proxies=True) as session:
        agent = client.Agent(session=session, max_steps=15)
        return agent.run(
            task=(
                f"Log into the Acme portal as {account_id} and list "
                f"invoices from the last {days_back} days."
            ),
        ).output
main.py
# deploy.py — register the handler and invoke it
from notte_sdk import NotteClient

client = NotteClient()

# Deploy the handler. Returns a function ID; the function is now callable.
function = client.Function(
    path="acme_invoices.py",
    name="acme-invoices",
    description="List recent invoices from the Acme supplier portal.",
)

# Invoke it. A fresh browser spins up, the handler runs, the result comes back.
result = function.run(account_id="acct_123", days_back=30)

The handler signature is the API shape. Whatever arguments run(...) takes are what callers pass; whatever it returns is what callers get back. Add a Pydantic model on the way out and you have a typed API in roughly twenty lines.

When to use a function vs. a session vs. an agent

Three primitives that overlap and confuse newcomers. The clean rule:

Use when
client.Session(...)Single ad-hoc workflow, called from your own code
client.Agent(session=...)Letting an LLM drive the session toward a natural-language goal
client.Function(...)The above, but it should be callable from elsewhere

The function is the deployment shape. Anything that's a session-plus-agent script can run as a function; anything that needs to be callable by another team, another system, a cron, or an end-user should be a function.

What "serverless" actually buys you

Three concrete properties:

  • No fleet to operate. No autoscaling group, no warm pool, no instance count to tune. The platform spins up browsers on demand.
  • Pay-per-invocation pricing. Idle functions cost nothing. The right shape for low-utilization workloads — most agent products are bursty.
  • Automatic concurrency. Two callers, two parallel invocations. Two thousand callers, two thousand parallel invocations (subject to account limits). No queue to write.

These are exactly the AWS-Lambda-shaped properties most engineers expect from "serverless." The browser is the new part.

Common pitfalls

  • Putting a long-running task into a function. Functions are for stateless invocations. Long-running orchestrations should use durable execution instead.
  • Cold start in latency-sensitive paths. First invocation pays a 1–3 second cold start. UX-critical paths may need a warm fallback or a scheduled keepalive.
  • No verifier. The handler returns whatever the agent produced. Without a verifier, "success" means "agent stopped." Add one before relying on the output.
  • Hard-coded credentials in the handler. Pass them in via parameters or use credential vaulting.

Key takeaways

  • A serverless browser function is your handler code + a per-invocation cloud browser + the deploy/scale/observability layer, packaged as a callable HTTP endpoint.
  • The platform handles everything except the handler — no fleet, no autoscaling, no warm pool to manage.
  • The deployment shape underneath the Anything API and the right primitive for browser work that should be callable from elsewhere.
  • Cold-start, no built-in long-running orchestration — use durable execution when the run takes more than a few minutes or needs to survive restarts.

Build your AI agent on the open web with Notte

Cloud browsers, agent identities, and the Anything API — everything you need to ship reliable browser agents in production.