Notte
SkillWeb & browsingLets your agent run browser automations, log in securely, and deploy scheduled web tasks as callable APIs.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Notte skill
About this capability
Deploy browser automations as scheduled, API-callable serverless Functions — plus stealth sessions, vault-backed login, captcha solving, and natural-language agent runs via the Notte CLI. Turns any browser flow into a deterministic Bitterbot-callable endpoint, ideal for crystallized skills + dream-e
What this skill tells your AI
The instructions your AI receives, as published by bitterbot-ai/bitterbot-desktop in skills/notte/SKILL.md and read by ahel’s review.
Hosted browser infrastructure with a CLI that does three things the bundled browser tool and Firecrawl cannot:
- Functions — deploy a browser automation script as a serverless, API-callable endpoint with built-in cron scheduling. The natural fit for crystallized skills and dream-engine cycles.
- Vault-backed login — passwords auto-fill on matching URLs without ever entering the model's context.
- Stealth sessions — residential proxies + inline captcha solving, for sites where the bundled Chromium gets locked out.
Functions — deploy a browser flow as a callable API
Crystallized skills and dream-cycle automations both want the same thing: a stable, repeatable browser action the agent can call by name on a schedule. Notte Functions is exactly that.
# 1. Capture an agent's run as deterministic Python (or hand-write it).
notte agents workflow-code # exports the latest agent's steps as Python
notte sessions workflow-code # or export from a CLI session
# 2. Deploy the script as a Function (one-shot — no servers, no infra).
notte functions create --file workflow.py
# → returns function_id
# 3. Run on demand, or schedule.
notte functions run # one-off
notte functions schedule-set --cron "0 */2 * * *" # every 2h, matches dream cycles
notte functions runs # invocation history
notte functions fork # version forward without losing the original
# 4. Or invoke via HTTP from anywhere (skill scripts, gateway hooks, channels).
curl -X POST https://api.notte.cc/functions/{function_id}/runs/start \
-H "Authorization: Bearer $NOTTE_API_KEY" \
-d '{"url":"https://example.com","query":"laptop"}'
Why this matters for Bitterbot:
- A crystallized skill that ends in "open this URL and grab the data" can be backed by a Function — fast, deterministic, no LLM tokens per execution.
- Function
schedule-setaligns directly with dream-engine cron triggers (every 2h consolidation, daily syncs, hourly monitors). notte agents workflow-codeis structurally the same pattern as Bitterbot's dream engine crystallizing execution paths — the agent figures out the steps, then the deterministic Function takes over for production.- Functions auto-inherit Notte's session capabilities: vault credentials, stealth proxies, captcha solving — without re-deploying anything.
When to use Notte vs the bundled tools
| Need | Use |
|---|---|
| Open a tab, click around, take a snapshot | Bundled browser tool (src/browser/) |
| Pull a single page through a stealth fetch | Firecrawl via web_fetch (docs/tools/firecrawl.md) |
| Crystallize a recurring browser flow into a callable API endpoint | notte functions |
| Schedule a browser flow on a cron (dream-cycle aligned) | notte functions schedule-set |
| Run a multi-step task on an authenticated site | notte session |
| Log in without exposing the password to the LLM | notte vault |
| The bundled browser is being challenged with captcha / Cloudflare / DataDome | notte (--solve-captchas, --proxy) |
| Need a residential / geo-located IP | notte |
| Hand a browsing goal to an agent and get a structured answer | notte agents |
notte does not replace the bundled browser. It's the deployment + infrastructure layer for browser flows that need to outlive a single agent run.
Setup
# Install (handled by the install metadata above).
brew tap nottelabs/notte-cli https://github.com/nottelabs/notte-cli.git && brew install notte
# or:
go install github.com/nottelabs/notte-cli/cmd/notte@latest
# Authenticate. Stores the API key in the system keyring.
notte auth login
# or: export NOTTE_API_KEY=...
Quick start
notte sessions start --proxy --solve-captchas
notte page goto "https://news.ycombinator.com"
notte page observe
notte page scrape --instructions "Top 10 story titles, points, and URLs as JSON"
notte sessions stop -y
observe returns interactive element IDs (@B3, @I1, @L9). Use those with click / fill, or fall back to Playwright selectors (#submit, button:has-text('Submit')) — both are accepted.
Vault-backed login (the biggest UX win over the bundled browser)
docs/tools/browser-login.md recommends manual login because automated logins trigger anti-bot defenses and can lock the account. Notte fixes this: store credentials in a vault and the browser auto-fills on matching URLs. The agent never sees the password.
notte vaults create --name "myservice"
notte vaults credentials add --vault-id <vault-id> \
--url "https://myservice.com" \
--email "user@example.com" \
--password "..." \
--mfa-secret "<TOTP_BASE32_SECRET>" # optional TOTP
notte sessions start
notte page goto "https://myservice.com/login"
# Credentials auto-fill from the matching vault entry.
This unblocks autonomous flows during dream cycles where there's no user available to log in manually.
Agent runtime (delegate the whole task)
For multi-step goals, hand the task to a Notte agent:
notte agents start --task "Find the cheapest non-stop SFO→CDG flight on Sep 14 and return the URL"
notte agents status
notte agents replay # session recording / step trace
Agents are cheaper than authoring step-by-step CLI calls when the task has many branches.
Stealth flags worth knowing
| Flag | Effect |
|---|---|
--proxy | Route through Notte's residential proxy pool |
--proxy-country <c> | ISO country code (us, gb, fr, de, …) |
--solve-captchas | Auto-solve reCAPTCHA / hCaptcha / Cloudflare turnstile |
--user-agent <ua> | Pin a specific UA string |
--cdp-url <url> | Bring-your-own remote browser (e.g. Lightpanda) |
--headless=false | Required when --cdp-url points to Lightpanda Cloud |
Page actions (cheat sheet)
notte page click "@B3" | "#submit-button"
notte page fill "@I1" "hello" # add --enter to submit
notte page check "#tos"
notte page select "#country" "France"
notte page upload "#file" --file ./report.pdf
notte page download "@L5"
notte page eval-js 'document.title'
notte page screenshot
notte page wait 500
notte page press "Enter" | "Escape" | "Tab"
notte page scroll-down [px] | scroll-up [px]
Navigation: goto, back, forward, reload, new-tab, switch-tab, close-tab.
Structured extraction
notte page scrape --instructions "Every job posting: title, company, location, salary range" -o json
notte page scrape --instructions "Article body and author" --only-main-content
Note: for routine single-page extraction without auth or anti-bot needs, web_fetch (with Firecrawl) is the lighter path. Use notte page scrape when extraction lives behind login or after a multi-step navigation.
MCP path (no install required)
Notte ships an MCP server (notte-mcp). It can be called through the existing mcporter skill without installing the Notte CLI:
NOTTE_API_KEY=... mcporter call --stdio "uv run --with notte-mcp python -m notte_mcp.server" \
notte_scrape url=https://example.com instructions="Extract pricing tiers"
Use the CLI by default — the MCP path is mainly useful inside flows already orchestrating MCP calls.
Live viewer (debugging)
notte sessions start -o json | jq -r '.viewer_url'
# or
notte sessions viewer
Environment variables
| Variable | Purpose |
|---|---|
NOTTE_API_KEY | API key (alternative to notte auth login) |
NOTTE_SESSION_ID | Default session for page commands |
NOTTE_API_URL | Override API endpoint |
NOTTE_MCP_SERVER_PROTOCOL | stdio or sse (only for the MCP server) |
Tips
- Always
observebeforeclick/fill/scrape. Element IDs come from observe output. - After every navigation,
observeagain — IDs are scoped to the current DOM snapshot. - Stop sessions you start.
notte sessions stop -yskips the prompt. Idle sessions cost API budget. - Lightpanda +
--cdp-urlrequires--headless=false. Otherwise the CDP server returns 500. @B3clicking the wrong element? Fall back to a Playwright selector.- Modals blocking clicks?
notte page press "Escape"thennotte page wait 500.
Troubleshooting
| Symptom | Fix |
|---|---|
| Site keeps blocking / shows captcha | Restart with --proxy --solve-captchas |
| Empty / partial scrape | Add notte page wait 1000 then re-observe before scrape |
@B3 clicks the wrong thing | Use a Playwright selector (button:has-text('Submit')) |
| Lightpanda CDP returns 500 | Add --headless=false to sessions start |
| Agent stuck on a captcha | Stop session, restart with --solve-captchas |
| 401 / auth errors | Re-run notte auth login or set NOTTE_API_KEY |
Signals
- GitHub stars
- 2k
- Forks
- 417
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
notte- Source
- github.com/bitterbot-ai/bitterbot-desktop