dots is a free, open source data extraction & web scraping project written in Python and released under MIT. It has 1,942 GitHub stars, 320 forks and 0 open issues, and was last pushed 30 hours ago. On this registry it ranks #73 of 124 tracked projects in Data Extraction & Web Scraping, with 5 head-to-head comparisons available.

What is dots?

dots is an open-source AI web agent that ships with its own anti-detect Firefox browser, aimed at developers and automation engineers who need an agent to browse, log in and click through real websites without being blocked.

What it is

dots is a Python project, MIT licensed, that pairs a language model with a browser built for automation. The model is any model available on OpenRouter, selected with the --model flag, while the browser is a real Firefox engine patched in C++. The project's premise is that every AI agent is a model plus a browser, and that while the model can be swapped with one flag, the browser is what the website actually sees. The interface runs as a local web page where the conversation sits on the left and the live browser on the right.

The concrete problem it addresses is web-agent failure caused by the browser rather than the model: a page that never loads, a challenge that appears, a login that expires, or a click that does not land. Dots is built around making that layer reliable. Its fingerprint is decided inside the engine rather than painted over with JavaScript a page can inspect, and no WebDriver flag, DevTools protocol or automation globals are exposed to the page. Pointer movements travel to the element that is clicked and keys are pressed one at a time, so every event the page receives is a trusted one.

Key capabilities

  • A real Firefox engine patched in C++, so the fingerprint is set inside the engine rather than emulated by page-inspectable JavaScript.
  • One identity per seed: screen, fonts, GPU, timezone and language agree with each other, and --seed returns the same identity on every run.
  • --profile-dir persists logins and cookies from one run to the next.
  • --proxy makes the timezone and language follow the exit node the connection is made from.
  • --model swaps the underlying language model, which can be any model on OpenRouter, with --openrouter-key supplying the credential.
  • Natural-language multi-step browsing tasks, such as checking flight fares across a range of dates and reading the cheapest fare for each day without guessing unavailable numbers.
  • The same browser is exposed as a server through the companion project invisible_playwright_mcp for MCP clients.

Who uses it and how

  • Developers running a local agent session at http://127.0.0.1:8765, keeping the conversation and the live browser side by side while working through a task.
  • Users of Claude Code, Codex, Gemini CLI or any MCP client who attach invisible_playwright_mcp to give their existing assistant this browser as a server.
  • Automation engineers who need repeatable identities across runs, using --seed so the same person is presented every time.
  • Operators who combine --proxy with a persistent --profile-dir to keep a login alive across sessions while the traffic exits from a chosen location.
  • Command-line users on Windows (PowerShell) or Linux who install via uv and launch with uvx.

Getting started

Install uv, then run uvx --from git+https://github.com/feder-cr/dots dots --openrouter-key sk-or-... and open http://127.0.0.1:8765; dots --help lists every option.

How it compares

Among the tools named in its own documentation, dots is the browser layer that Claude Code, Codex and Gemini CLI do not provide themselves; it hands those assistants the browser through invisible_playwright_mcp as a server, with dots serving as its interface. It therefore complements those assistants rather than competing with them, supplying the anti-detect Firefox engine they would otherwise borrow from a generic Playwright installation.

When to use it — and when not

A self-hoster runs a local server on port 8765 and must supply an OpenRouter API key, so the model side is tied to that provider even though the model itself is swappable. It is not a good fit for teams that want a hosted service, a non-Firefox engine, or a model outside OpenRouter. The README is terse, and the anti-detect and patched-engine claims are the kind best verified against a target site before relying on them.

project readme (upstream, from github) — read inline

dots

Every AI agent is a model and a browser.
You can swap the model with one flag. The browser is what the website sees.


Windows, in PowerShell:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
$env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
uvx --from git+https://github.com/feder-cr/dots dots --openrouter-key sk-or-...

Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env
uvx --from git+https://github.com/feder-cr/dots dots --openrouter-key sk-or-...

Then open http://127.0.0.1:8765. The conversation on the left, the browser on the right, live.

It all comes down to the browser

When a web agent fails, the model is rarely why. The page never loaded, a challenge appeared, the login expired, the click did not land. All of that happens in the browser, before the model gets to think.

So dots is built around one:

  • A real Firefox engine, patched in C++. The fingerprint is decided inside the engine, not painted over with JavaScript that a page can inspect.
  • One identity per seed. Screen, fonts, GPU, timezone and language agree with each other, and --seed gives back the same person on every run.
  • Nothing for a page to find. No WebDriver flag, no DevTools protocol, no automation globals in the page.
  • A person's hands. The pointer travels to what it clicks and keys are pressed one at a time, so every event the page receives is a trusted one.
  • A browser that remembers. --profile-dir keeps logins and cookies from one run to the next.
  • Where it connects from is who it is. With --proxy, the timezone and the language follow the exit.

The model is any model on OpenRouter, and --model changes it.

What to ask it

Go to ``. One way, Milan to Lisbon, economy, one adult. Check every date from the 12th to the 16th of next month and read the cheapest fare for each day. If a date has no availability, say so. Do not guess a number.

The same browser, in your own assistant

Claude Code, Codex, Gemini CLI or any MCP client: invisible_playwright_mcp gives them this browser as a server. dots is its interface, and dots --help lists every option.


Not affiliated with OpenAI. MIT licensed.

Frequently asked questions

Is dots free to use?

dots is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does dots do?

Open-source dots for the web: an AI agent with its own browser, one that does not get blocked.

What is dots written in?

dots is primarily written in Python. Its source is publicly available at https://github.com/feder-cr/dots, and it has 1,942 GitHub stars.