Model or dataset
feder-cr/AIHawk avatar
feder-cr/AIHawk

AIHawk: an MCP browser agent that drives a real Firefox, and the licence split you need to notice

Open-source AI browser agent for web automation: a web browsing agent and computer-use agent in plain English. Browser MCP for Claude Code and Gemini CLI.

31,595 stars4,664 forksPythonMIT

At a glance

What is it?
AIHawk wraps a stealth Firefox build behind an MCP server and a local web UI, so Claude Code or Gemini CLI can click through pages a plain HTTP client cannot reach. The interesting parts are the pinned engine binary, the config precedence rules, and a licence change that only applies after 2 September 2026.
Who is it for?
Adopt AIHawk if you already drive Claude Code, Codex or Gemini CLI and want page interaction exposed as an MCP tool without writing Playwright code, and if you are comfortable pointing an autonomous agent at sites whose terms you have read. Do not adopt it if you need a stable scripting API, if you cannot tolerate a pinned engine build that must match the seal exactly, or if you are running it against a site where a wrong click has consequences.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
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 gap AIHawk fills: pages that only exist after a click

Most LLM tooling reaches the web through an HTTP fetch and a text extraction step. That works for documentation, changelogs and article bodies. It fails the moment the answer sits behind a calendar widget, a date picker, a multi-step form, or a login that sets a session cookie. The README's own worked example is a flight search: one way, Milan to Lisbon, economy, one checked bag, one adult, checking every date from the 12th to the 16th and reading the cheapest fare for each. The prompt explicitly tells the agent that the date field is a calendar widget, so it should click the days rather than type them, and that it must not guess a number when a date has no availability. That instruction is the whole point. The agent is being asked to look at the rendered page and report what it actually sees, not to synthesise a plausible fare.

The audience follows from that. It is people who already have an assistant open in a terminal and want it to touch a live page: job hunting, lead generation, price monitoring, market research, the topics the repository lists. It is not a scraping framework and it is not a headless HTTP client with a rendering engine bolted on. The README frames it as driving the page the way a person would, with the pointer moving and keys being pressed. If your task can be done with a GET request and a parser, this is heavier than you need.

Two entry points, one package, and the engine underneath

The repository ships a single package that behaves differently depending on how it is invoked. Run `aihawk` with no subcommand and you get the MCP server, which is what option 1 installs. Run `aihawk ui` and you get a local interface on the left and a live view of the browser on the right. Both are the same agent; only the transport differs. The MCP route registers the server under the name `stealth` in the client, which is why the add commands read `claude mcp add --scope user stealth -- uvx aihawk`.

Underneath, the browser is not stock Playwright. The engine is a separate project, invisible_playwright, distributed as a Python library whose API is Playwright's. A third project, invisible_core, handles the mapping from seed to fingerprint to preferences, proxy and geolocation. That layering explains the `--seed` flag: an integer that produces the same browser identity on every run. It also explains why the proxy option is not just a network setting. The README states that timezone, locale and egress follow the proxy, so the browser's advertised locale and clock move with the exit node rather than staying at whatever the host machine reports.

The MCP registration is deliberately thin. Three clients are documented with one-line commands, and the README notes that config blocks for clients which take a file, along with the server's settings and its tool list, live on the wiki page titled The MCP server. That page is where you would look to find out what tools the agent actually exposes, because the README does not enumerate them.

Install: uv, a fetched engine, and a key you should not type on the command line

Every documented path starts with uv. On Windows in PowerShell, `powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"`, then prepend `$env:USERPROFILE\.local\bin` to the path. On Linux, `curl -LsSf https://astral.sh/uv/install.sh | sh` followed by `source $HOME/.local/bin/env`. Both are followed by `uvx invisible-playwright fetch`, which retrieves the engine binary. Only after that does `uvx aihawk ui --openrouter-key sk-or-...` or an MCP registration make sense.

The configuration surface is small and the precedence is stated explicitly: `--flag` beats the environment, which beats `.env`, which beats the default. The `.env` file is read from the directory you run in and there is no upward search, so invoking from a subfolder cannot quietly pick up a different key. The startup line names the variables it applied without printing their values. Two keys are documented there: `OPENROUTER_API_KEY` and `STEALTHFOX_BINARY`.

The README makes a security argument that is worth repeating because it is unusual to see stated so plainly: passing `--openrouter-key` puts the key in your shell history and, on Linux, in the process list. Putting it in the environment or a `.env` avoids both. The host and port flags default to `127.0.0.1` and `8765`, and the README warns that changing the host exposes an interface with no authentication. That is not a hedge, it is a statement that the UI has no login.

The pinned binary is a constraint, not a convenience

The `--binary` flag lets you point AIHawk at an engine you already have instead of downloading one. The README is blunt about the limits: it must be the build the seal pins, or startup refuses. The flag skips the download, not the version check. Anyone hoping to substitute a system Firefox, or to hold a working build while the pinned one changes, will find that this does not work. The engine version moves with the package version, and the three releases listed in the repository metadata, v0.37.0, v0.38.0 and v0.39.0, all landed on 10 September 2026, with the first two in the same day. That cadence tells you something practical: if you pin AIHawk to a version for stability, you are also pinning the engine, and you will need to re-run the fetch step whenever you move.

The `--profile-dir` flag points the other way. Give it a directory and logins and cookies survive restarts, which is what makes multi-session work possible at all. Without it, every run starts from a clean profile and any task behind a login begins with the login flow. The `--headed` flag shows the browser window, though the README notes the UI shows you the page anyway, which suggests headed mode is mainly for debugging the agent's behaviour rather than for watching it work.

There is no documented retry, timeout or step-limit configuration in the material provided. If the agent loops on a page, the README does not say what stops it. That absence is worth knowing before you point it at a long task.

Where it is the wrong tool

The README's own responsibility section is the honest part of the document. It says the software automates a browser under your control, that you should read the terms of the sites you point it at, respect their rate limits, and not submit anything a human has not read. That last clause is doing a lot of work, and it cuts against the automation premise. A job application submitted by an agent that no one reviewed is exactly the failure mode the press coverage around this project described, and the README does not pretend otherwise.

The technical limits matter too. Because the agent reads the rendered page and decides what to click, its behaviour is not reproducible in the way a script is. The same prompt against the same page can produce a different sequence of interactions. For a one-off research question that is fine. For a scheduled job that must run identically every night, it is a poor fit. There is no assertion mechanism documented, no way to say "fail unless this element contains that value". The flight example handles this with a prompt instruction, telling the agent not to guess a number, which is a request rather than a guarantee.

Cost and latency are the other side of it. Each step is a model call against an OpenRouter model, and the default is `z-ai/glm-5.3-flash`, with `--model` or `AIHAWK_MODEL` to change it. A task that clicks through five dates is not one request. The README does not publish token counts or per-task costs, so you should measure that yourself before committing to a volume-heavy workflow.

The alternative: write the Playwright script yourself

The obvious comparison is invisible_playwright, the engine AIHawk depends on, used directly as a Python library. The README describes it as the option for writing code instead of prompts, and notes the API is Playwright's. The difference in approach is not cosmetic. With the library you write the selectors, the waits and the assertions, and the browser does exactly what you told it. With AIHawk you describe an outcome and the model decides which element to interact with next.

That trade runs in both directions. A script is deterministic and cheap to re-run, but it breaks the moment the site changes a class name or reorders a form, and it cannot handle a page whose structure you did not anticipate. The agent survives layout changes because it is reading the page rather than matching a selector, but it costs a model call per step and can take an unexpected path. If you have already written Playwright code and it works, AIHawk adds a model in the loop without removing the maintenance burden, because you still have to keep the engine version current.

The wiki page comparing browser-use, Operator-style and computer-use agents is the place to look if you want the project's own framing of where it sits among those approaches. The README points to it under the guides section, alongside pages on why agents get blocked and what happened to OpenAI Operator. Those are the project's claims, not independent measurements.

Maintenance, licence, and what the version history implies

The licence situation needs care. The repository is MIT now, but the README states that everything distributed before 2 September 2026 was released under AGPL-3.0 and stays under it. If you vendored an older release, or built a service on one, the terms you took it under have not changed. The MIT grant applies to what came after. This is not a legal opinion, and if the distinction matters to your distribution model you should read the LICENSE file and the release dates yourself rather than trusting a summary.

The maintenance picture is a small team moving fast. Three releases on the same day, with the last push timestamp matching the newest release, suggests active work. It also suggests that pinning to a version is the only way to get a stable engine, and that the pin will need attention. The engine binary is fetched separately via `uvx invisible-playwright fetch`, so an upgrade is two steps rather than one, and a stale binary after a package upgrade will be rejected at startup rather than silently tolerated.

For a personal tool run from a terminal, that is a manageable rhythm. For anything embedded in a pipeline other people depend on, the version check is the thing to design around, because it fails closed. A scheduled job that upgrades the package but not the engine will not degrade, it will stop.

Editorial conclusion

Adopt AIHawk if you already drive Claude Code, Codex or Gemini CLI and want page interaction exposed as an MCP tool without writing Playwright code, and if you are comfortable pointing an autonomous agent at sites whose terms you have read. Do not adopt it if you need a stable scripting API, if you cannot tolerate a pinned engine build that must match the seal exactly, or if you are running it against a site where a wrong click has consequences. Before anything else, check which licence covers the version you are about to depend on: everything distributed before 2 September 2026 is AGPL-3.0 and stays there, while the current tree is MIT. Then run uvx invisible-playwright fetch and confirm the binary version it downloads is the one --binary will accept, because startup refuses any other build.

Official sources

  1. feder-cr/AIHawk on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes