Model or dataset
nottelabs/notte avatar
nottelabs/notte

Notte: a Python web agent framework with a hosted browser tier behind it

Cloud browser infrastructure and web automation platform for your AI and coding agents

2,002 stars182 forksPythonNOASSERTION

At a glance

What is it?
Notte is an open source Python SDK for driving browsers with an LLM, plus a paid API service that adds stealth sessions, credential vaults and digital personas. The split is the interesting part: what you can run yourself and what you cannot.
Who is it for?
Adopt Notte if you want a Python-first agent loop you can run locally with your own LLM keys and then move to hosted sessions without rewriting the code, and if SSPL-1.0 is acceptable for how you plan to deploy it. Do not adopt it if you need a permissively licensed library for a commercial product you cannot open source, or if you want a framework whose browser layer you fully control.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Notte targets: browser agents that are expensive and flaky

Most LLM browser agents re-ask the model about every click. Each step costs a request, each request costs latency, and any single misread of the page derails the run. Notte's README frames the fix as a hybrid: script the deterministic parts of a workflow and call the model only where the page is genuinely unpredictable, which the project claims cuts costs by 50 percent or more. That claim is the project's own, not a measured result, and the README does not break down how the number was derived.

The audience is Python developers building web automations that need to survive real sites: login flows, form filling, scraping behind a session, multi-step tasks that span several pages. Notte is not aimed at someone who wants a no-code recorder, and it is not aimed at someone scraping static HTML where requests and BeautifulSoup already work.

Two runtimes, one API: local open source core versus the hosted SDK

The repository ships two entry points that mirror each other. The open source path imports notte directly, constructs a notte.Session, and attaches a notte.Agent with a reasoning_model and a max_steps budget. The hosted path imports NotteClient from notte_sdk, constructs client.Session and client.Agent, and passes an API key from the NOTTE_API_KEY environment variable. The README states the intent explicitly: experiment locally, then drop-in replace the import and prefix the objects with client to get hosted browser sessions plus premium features.

That symmetry is the design decision worth noting. It means the agent loop and the session abstraction are the same shape in both modes, so the migration cost is mostly mechanical. It also means the interesting capabilities sit on one side of the line. Stealth sessions with CAPTCHA solving and proxies, secrets vaults, and digital personas are listed under the API service, not the open source core. The open source core is the agent, structured output, and Playwright-compatible site interactions.

What the agent loop actually does with a page

From the code samples, the flow is: open a session (optionally with open_viewer=True to watch it, and browser_type to pick a browser), create an agent bound to that session with a reasoning model string such as gemini/gemini-2.5-flash and a step ceiling, then call agent.run(task=...) with a natural language instruction. The agent observes the page, decides on an action, executes it through Playwright-compatible primitives, and repeats until the task completes or max_steps is exhausted.

The step ceiling is the part that matters operationally. It is a hard stop, not a suggestion, and it is the main lever you have over both cost and runaway loops. Setting max_steps=30 for an open-ended browsing task and max_steps=10 for a login flow, as the README examples do, is the practical way to bound spend. There is no described mechanism in the supplied material for resuming a run that hit the ceiling, so a task that needs more steps than your budget simply fails at that point.

The reasoning model is passed as a string in litellm-style provider/model form, which suggests the model layer is pluggable across providers. The topics list (anthropic, openai, llm) is consistent with that, though the README only demonstrates a Gemini model.

Structured output, vaults and personas: three features with different owners

Structured output is in the open source core. You define a Pydantic model, pass it as response_format to agent.run, and read the result from response.answer. The README's Hacker News example nests a list of post models inside a TopPosts wrapper, which is the standard Pydantic pattern and means your downstream code gets typed objects rather than a string you have to parse. This is the feature most likely to decide adoption for data extraction work, because it removes an entire class of prompt-and-parse glue.

Vaults and personas are different. The vault example opens client.Vault() as a context manager, calls vault.add_credentials(url=..., username=..., password=...) and attaches it to the agent, so the agent can log in without the credentials appearing in the task text. The persona example opens client.Persona(create_phone_number=False) and the README describes unique email addresses, phone numbers and automated 2FA. Both are documented under the API service section, so on the evidence available they are hosted features. If you run purely locally, plan on supplying credentials through your own mechanism and handling 2FA yourself.

One detail worth flagging: the persona sample is truncated mid-line in the README, ending inside a client.Session call. That is a documentation defect, not a capability statement, but it means the example as published does not run as shown.

Getting it running: two commands and an environment variable

Installation is a pip install of the notte package followed by patchright install --with-deps chromium. Patchright is the stealth-oriented Playwright fork, so the browser binary comes from there rather than from a standard Playwright install. For the local path you supply your own LLM API keys; the README example loads them with python-dotenv from a .env file.

For the hosted path you sign up on the Notte Console and create an API key, then export it as NOTTE_API_KEY. There is no self-hosting path for the hosted features described in the supplied material, and no configuration keys beyond the ones visible in the code samples: open_viewer, browser_type, reasoning_model, max_steps, response_format, and the vault's url, username and password arguments. If you need to know what a session costs or what limits apply to hosted sessions, the README does not say; that information would be on the console or in the docs site.

The licence is the first thing to check, and the badge is not the answer

The repository metadata reports the licence as NOASSERTION, while the README badge links to SSPL-1.0. Those two signals disagree, and the difference matters. SSPL is a copyleft licence written for service software: it is not OSI-approved, and its obligations extend to anyone who offers the program as a service. For a developer building internal automation, that may be irrelevant. For a company that wants to wrap the framework in a product it sells as a hosted service, it is the central question, and it is not one this article can answer for you.

Before writing code against Notte, read the LICENSE file in the repository itself rather than trusting the badge or the metadata field. If your legal position depends on permissive terms, treat this as unresolved until you have read the actual text.

Where Notte is the wrong choice, and what to compare it against

The clearest limitation is the split between the open source core and the hosted service. The features that make browser automation survive contact with production sites (CAPTCHA solving, proxies, anti-detection) are hosted-only according to the README's own categorisation. If your requirement is a fully self-contained agent that handles hostile sites, the local mode does not claim to do that, and you would be building the missing pieces yourself.

The second limitation is the step budget. A max_steps ceiling with no described resume path means long-horizon tasks are bounded by how well you can predict the step count in advance. Complex multi-page workflows may need to be decomposed into several agent runs stitched together by your own code, at which point you are writing the orchestration the framework was supposed to provide.

The natural alternative is browser-use, which appears in Notte's own benchmark table with lower self-reported and evaluated scores and a longer time per task. The difference in approach is worth stating plainly: browser-use is a library you run yourself, while Notte pairs an open source library with a hosted browser tier and pushes the anti-bot and identity features into that tier. If you want one dependency you fully control and you are willing to handle stealth yourself, browser-use fits that shape better. If you would rather buy the browser infrastructure and keep your code in Python, Notte's split is the point.

Note also that the benchmark table is published by Notte about Notte, with an accompanying open-operator-evals repository. It is a self-reported comparison, not an independent one.

Maintenance cadence and what a version bump costs you

The release history shows a fast cadence: v1.8.39, v1.8.40 and v1.8.41 land on consecutive days in September 2026, and the last push to main is the same day as the newest release. Daily patch releases on a 1.8.x line usually mean active bug fixing rather than a stable API surface. Nothing in the supplied material describes a deprecation policy, a support window for older versions, or whether the notte and notte_sdk packages version together.

For a project using Notte, that cadence has a concrete cost: pin your version in requirements.txt or pyproject.toml rather than tracking latest, because the README's own examples are the API contract and they can change between patches. The Python 3.11+ badge sets a floor on your interpreter. There is no stated upgrade guide in the material provided, so the practical verification step before each bump is to re-run your own agent tasks against the new version, not to read a changelog that may not exist.

Editorial conclusion

Adopt Notte if you want a Python-first agent loop you can run locally with your own LLM keys and then move to hosted sessions without rewriting the code, and if SSPL-1.0 is acceptable for how you plan to deploy it. Do not adopt it if you need a permissively licensed library for a commercial product you cannot open source, or if you want a framework whose browser layer you fully control. Before committing, verify the licence terms in the repository rather than the badge, confirm that the local extras (proxy rotation, CAPTCHA handling, vaults, personas) are really server-side only, and decide whether you accept a hosted dependency for the parts that matter most to production.

Official sources

  1. Issues
  2. nottelabs/notte on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes