You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It was explaining instead of instructing. Two mermaid diagrams asked the reader
to understand an architecture before running anything, and a whole section
argued why the browser gets challenged less, which is the browser project's
material rather than this one's. Neither told anyone what to type.
The file is now organised around what the reader came for, documents or a
browser his AI drives, and he reaches the first command 27 lines in. Half the
length, 13496 bytes down to 7145.
Nothing was traded away for the shorter version. Still findable: there is no
captcha solver, nothing fills and submits an application end to end, only OpenAI
works, and the MCP server is a package rather than something in this repository.
@@ -19,46 +17,11 @@ The first half runs from this repository today. The second ships as installable
19
17
20
18
---
21
19
22
-
## Where this stands
23
-
24
-
AIHawk went viral in 2024 as a bot that applied to jobs for you. That is the
25
-
version the press above wrote about, and the mass-application engine is no longer
26
-
in this repository.
27
-
28
-
It was removed for a reason worth stating plainly. Firing applications at a job
29
-
board is the easy half and the worthless half. It stops working the moment the
30
-
site decides you are a machine, and it produces the kind of volume that made
31
-
recruiters hate the whole category. The half that was actually hard, and that
32
-
survived, is a browser that reaches the end of a task without being stopped.
33
-
34
-
So AIHawk is two things now, and this README is careful about which is which:
35
-
36
-
**In this repository, runnable today:** the document half. An LLM reads your
37
-
profile and a job posting and writes a resume or a cover letter for that specific
38
-
posting. It is a local command line tool, it works, and CI checks it on every
39
-
push.
40
-
41
-
**As separate installable packages:** the browser half. A Firefox patched at the
42
-
source, exposed to any AI client over MCP. You install it with one command and
43
-
never clone anything.
20
+
The 2024 mass-application bot the press wrote about is not in this repository any more. It is still in the git history if you forked it and want to compare, but it is unmaintained and will not work against anything current. What is here now, and what installs beside it, is below.
44
21
45
-
What joins them into one automated pipeline does not exist yet. That part is
46
-
honest roadmap, described at the bottom, not shipped code.
22
+
## I want documents
47
23
48
-
## The document half, in this repository
49
-
50
-
Generate a resume, a resume rewritten for a specific job posting, or a cover
The first run creates `data_folder/` for you, copied from the worked example, and
74
-
stops to say so. Open the three files it made and put your own details in:
75
-
`plain_text_resume.yaml` is your experience and skills, `work_preferences.yaml`
76
-
is what you are looking for, and `secrets.yaml` takes your OpenAI API key. Those
77
-
files are not in git, so what you write there stays yours.
36
+
That first run creates `data_folder/` from `data_folder_example/`, tells you which files to edit, and stops. Edit these three:
37
+
38
+
| File | Put in it |
39
+
|---|---|
40
+
|`data_folder/plain_text_resume.yaml`| Your experience and skills |
41
+
|`data_folder/work_preferences.yaml`| What you are looking for |
42
+
|`data_folder/secrets.yaml`| Your OpenAI API key |
43
+
44
+
They are git-ignored, so what you write there stays yours.
45
+
46
+
Run it again and pick one:
47
+
48
+
-**Generate Resume**
49
+
-**Generate Resume Tailored for Job Description**
50
+
-**Generate Tailored Cover Letter for Job Description**
78
51
79
-
Run it again and it asks which of the three documents you want, then writes the
80
-
PDF into `data_folder/output/`.
52
+
The two tailored options ask for a job posting URL and open it in Chrome. The finished PDF lands in `data_folder/output/`.
81
53
82
-
It calls OpenAI, on `gpt-4o-mini`. Other providers used to be wired up through
83
-
LangChain and are not any more: the code that offered the choice was removed with
84
-
the mass-application engine, so an Anthropic or Ollama key in `secrets.yaml` gets
85
-
handed to an OpenAI client and fails. Put an OpenAI key there, and keep it out of
86
-
your commits. There is a test in here that fails the build if a key ever lands in
87
-
that file again, because one did.
54
+
**Use an OpenAI key.** This calls `gpt-4o-mini`, and no other provider works: an Anthropic or Ollama key in `secrets.yaml` gets handed to an OpenAI client and fails.
88
55
89
-
## The browser half, as packages
56
+
## I want a browser my AI drives
90
57
91
-
This is the part that installs rather than clones, and none of it lives in this
92
-
repository.
58
+
It installs as a package, `invisible-playwright-mcp` on PyPI. None of it is in this repository, so there is nothing to clone here.
93
59
94
-
MCP is the protocol AI clients use to attach external tools. If you use
95
-
[Claude Code](https://claude.com/claude-code), Claude Desktop, Cursor or
96
-
anything similar, you already have a client. You need
97
-
[uv](https://docs.astral.sh/uv/) for the `uvx` command, Python 3.11 or newer, and
98
-
Windows or Linux.
60
+
You need [uv](https://docs.astral.sh/uv/) for the `uvx` command, **Python 3.11 or newer**, and **Windows or Linux**. If you use [Claude Code](https://claude.com/claude-code), Claude Desktop, Cursor or anything similar, you already have the client half.
99
61
100
62
```bash
101
63
claude mcp add stealth --env STEALTHFOX_PROXY=http://user:pass@host:port -- uvx invisible-playwright-mcp
102
64
```
103
65
104
-
Without a proxy, drop the `--env` flag. For any other client, the same thing as a
105
-
config entry:
66
+
Drop the `--env` flag if you are not using a proxy. In any other client, the same thing as a config entry:
106
67
107
68
```json
108
69
{
@@ -120,166 +81,52 @@ config entry:
120
81
}
121
82
```
122
83
123
-
Use an absolute path for the profile directory. Most clients pass env values
124
-
through verbatim, so a leading `~` becomes a folder literally named `~`.
84
+
Restart the client and list your MCP servers. `stealth` should be there with thirteen tools:
Restart the client and list your MCP servers. `stealth` should be there with
129
-
thirteen tools attached. Then type one small thing before you type a big one:
90
+
You never call those yourself, the model does. Ask it for one small thing first, like opening a page and taking a screenshot.
130
91
131
-
> Use the stealth browser to open a browser fingerprint check page, take a
132
-
> screenshot, and tell me the timezone, locale, languages and public IP it
133
-
> reports.
134
-
135
-
Read those four values against what your own browser reports on the same page. On
136
-
a proxied run they should describe the exit country and agree with each other,
137
-
not with the machine you are sitting at. That is the whole thesis, checkable in
138
-
one prompt, before you trust it with anything that matters.
139
-
140
-
The first launch downloads the patched Firefox build, a few hundred megabytes, so
141
-
it takes a minute and looks like a hang. It is cached afterwards. If the server
142
-
does not appear at all, `uvx` is not on the PATH the client sees, which is not
143
-
always the PATH your shell sees.
92
+
**The first launch downloads a few hundred megabytes** and looks like a hang. It is cached after that. If the server never appears at all, `uvx` is not on the PATH your client sees, which is not always the PATH your shell sees.
144
93
145
94
### Two things to ask it
146
95
147
-
The server drives the browser and only the browser: no disk access, on purpose.
148
-
Reading a file or writing a CSV is your client's own file tools.
96
+
The server drives the browser and nothing else: it has no disk access. Reading and writing files is your client's own tooling.
97
+
98
+
> Go to `<paste the URL>`. Filter to backend roles in Europe posted in the last two weeks. For each result, open the posting and pull out the title, the location, whether it says remote or hybrid, and anything about visa sponsorship. Give me the list as a table, and append a row to shortlist.csv for each one.
149
99
150
-
> Go to this careers page: `<paste the URL>`. Filter to backend roles in Europe
151
-
> posted in the last two weeks. For each result, open the posting and pull out the
152
-
> title, the location, whether it says remote or hybrid, and anything it says
153
-
> about visa sponsorship. Give me the list as a table, and append a row to
154
-
> shortlist.csv for each one: company, role, URL, date.
100
+
> Go to `<paste the URL>`. One way, Milan to Lisbon, economy, one checked bag, one adult. Check every date from the 12th to the 16th of next month, one at a time, and read the cheapest fare for each day. The date field is a calendar widget, so click the days rather than typing them. If a date has no availability say so, do not guess a number. Write the five to flights.md sorted by price, and leave the cheapest open in a tab.
155
101
156
-
> Go to this flight search site: `<paste the URL>`. One way, Milan to Lisbon,
157
-
> economy, one checked bag, one adult. Check every date from the 12th to the 16th
158
-
> of next month, one at a time, and read the cheapest fare for each day. The date
159
-
> field is a calendar widget, so click the days rather than typing them. If a date
160
-
> has no availability say so, do not guess a number. Write the five to flights.md
161
-
> sorted by price, and leave the cheapest open in a tab so I can book it myself.
102
+
### Settings
162
103
163
-
Those two share nothing except the machinery: same server, same browser, same
164
-
thirteen tools, nothing reconfigured in between.
104
+
| Variable | What it does |
105
+
|---|---|
106
+
|`STEALTHFOX_PROXY`|`http://user:pass@host:port`, or `socks5://`. Credentials go in the URL. |
107
+
|`STEALTHFOX_SEED`| An integer. Same seed, same browser identity, every run. Set one for anything you run more than once. |
108
+
|`STEALTHFOX_PROFILE_DIR`| Absolute path. Persistent profile, so logins and cookies survive restarts. Most clients pass env values through verbatim, so a leading `~` becomes a folder literally named `~`. |
109
+
|`STEALTHFOX_HEADLESS`| Headless by default. Set `0` to watch the window, worth doing the first few times. |
165
110
166
-
## Why fewer challenges appear
111
+
## Limits
167
112
168
-
An anti-bot rarely catches you on one exotic value. It catches you on a
169
-
contradiction. Put a proxy in front of an ordinary browser and you have built one:
170
-
the address says one country, the clock and the language say another.
113
+
**There is no captcha solver here.** None is built in and none is wired to a third party service.
171
114
172
-
```mermaid
173
-
flowchart LR
174
-
A["Proxy says: United States"] --> D{"Anti-bot compares"}
175
-
B["Browser says: Italy"] --> D
176
-
D --> E["Contradiction<br/>→ challenge"]
177
-
```
115
+
**Nothing joins the two halves yet.** No code in any of these repositories fills in an application form and submits it end to end. The generated PDF is something you upload yourself, and the browser is something you drive through prompts. There is no timeline attached to that.
178
116
179
-
The engine turns that around. Before the browser starts, the exit IP is resolved
180
-
through the proxy, and everything the browser will declare is derived from that
181
-
exit rather than from the machine the process happens to be running on. Values an
182
-
IP cannot imply, like screen metrics and GPU strings, come from
D --> E["Everything agrees<br/>→ nothing to raise a challenge about"]
192
-
```
117
+
## The other repositories
193
118
194
-
There is nothing incoherent in that declared layer to find, because it all comes
195
-
from one source. That is one input into a risk score among several, and it is the
196
-
input this project can do something about. The practical consequence: many of the
197
-
interstitials and hard blocks people expect from browser automation never appear,
198
-
because nothing raised them.
119
+
-[invisible_playwright](https://github.com/feder-cr/invisible_playwright) - the Python wrapper and the browser it pins and drives. Use this directly if you would rather script than prompt: the API is Playwright's.
120
+
-[invisible-playwright-mcp](https://github.com/feder-cr/invisible-playwright-mcp) - the MCP server installed above.
121
+
-[invisible_core](https://github.com/feder-cr/invisible_core) - seed to fingerprint to preferences, proxy and geolocation derivation.
122
+
-[lib_resume_builder_AIHawk](https://github.com/feder-cr/lib_resume_builder_AIHawk) - the resume rendering library this repository depends on.
199
123
200
-
**There is no captcha solver in this project.** No third party service wired up,
201
-
no pass rate to promise. Cloudflare, Turnstile, DataDome, Kasada, Akamai,
202
-
reCAPTCHA and hCaptcha all exist and all still work. What changes is how often
203
-
you meet one. When an interactive challenge does appear, `browser_click_at` gives
204
-
your client a real pointer: viewport coordinates, a pointer that moves rather than
205
-
teleports, press and hold, and a screenshot of what happened. That covers sliders
206
-
and press-and-hold widgets. It will not identify motorbikes for you, and sometimes
207
-
the honest answer to a challenge is to stop.
124
+
Issues and pull requests are welcome on whichever of those the problem lives in. If you are not sure, open it here. When something fails on a page, say which step, what the page did, what the tool returned and which exit country you were on. "It got blocked" is not something anyone can act on.
208
125
209
-
### Configuration
126
+
##Using it
210
127
211
-
| Variable | What it does |
212
-
|---|---|
213
-
|`STEALTHFOX_PROXY`|`http://user:pass@host:port`, or `socks5://`. Timezone, locale, languages, geolocation and egress all derive from it. |
214
-
|`STEALTHFOX_SEED`| An integer. Fixes the seeded half of the identity: fonts, screen, GPU strings. Same seed, same values, every run. |
215
-
|`STEALTHFOX_PROFILE_DIR`| Absolute path. Persistent profile, so logins and cookies survive restarts. |
216
-
|`STEALTHFOX_HEADLESS`| Headless by default. Set `0` to watch it work, worth doing the first few times. |
217
-
|`STEALTHFOX_BINARY`| A build of your own. Only for people building the engine themselves, and it needs a matching seal file or the launch is refused on purpose. |
218
-
219
-
Set a seed for anything you run more than once. An identity that changes shape
the resume rendering library this repository depends on.
265
-
266
-
Issues and pull requests are welcome on whichever of those the problem lives in.
267
-
If you are not sure, open it here. When something fails on a specific site,
268
-
describe the shape of it: which step, what the page did, what the tool returned,
269
-
which exit country. "It got blocked" is not something anyone can act on, and a
270
-
list of targets in the issue tracker helps nobody.
271
-
272
-
The 2024 command line applier is still in the git history if you forked it and
273
-
want to compare. It is not maintained and it will not work against anything
274
-
current. Third-party provider plugins are not in this repository: the core is
275
-
open source, the plugins were removed for copyright reasons.
276
-
277
-
## A note on use
278
-
279
-
This automates a browser under your control. Read the terms of the sites you
280
-
point it at, respect their rate limits, and do not use it to submit things a
281
-
human has not read.
128
+
This automates a browser under your control. Read the terms of the sites you point it at, respect their rate limits, and do not submit anything a human has not read.
0 commit comments