@aliasmode/anyfetch 0.0.0-stage → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +367 -2
- package/package.json +18 -4
- package/run.js +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,368 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Anyfetch
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Web search and web fetch for AI agents. One small binary, no API keys, and it reads the sites that refuse your agent.**
|
|
4
|
+
|
|
5
|
+
Free and open source, from the makers of [AliasMode](https://aliasmode.com/).
|
|
6
|
+
|
|
7
|
+
Agent harnesses fetch pages with a bot identity, and a large part of the web answers `403`. Anyfetch sends the request a real browser sends, so your agent gets the page.
|
|
8
|
+
|
|
9
|
+
| 97 popular sites that block AI agents | Pages read |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| **Anyfetch** | **75** |
|
|
12
|
+
| curl | 47 |
|
|
13
|
+
| Reference MCP fetch server | 41 |
|
|
14
|
+
| Claude Code built-in `WebFetch` | 36 |
|
|
15
|
+
|
|
16
|
+
Anyfetch read 21 sites that no other tool in the table could read. Among them: The New York Times, Reuters, Bloomberg, The Washington Post, Medium, Reddit, Stack Overflow and YouTube.
|
|
17
|
+
|
|
18
|
+
| 30 research questions, each asked twice | Answered correctly both times |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| **Agent with Anyfetch** | **30** |
|
|
21
|
+
| Same agent with Claude Code built-in `WebSearch` and `WebFetch` | 25 |
|
|
22
|
+
|
|
23
|
+
Ten of the questions are about a page on a site that blocks AI agents. The built-in fetch could not read any of those 10 pages. Its search found the answer in another source for 5 of them. Anyfetch read all 10. The questions were written from pages that Anyfetch can read, so this group shows what the built-in tools miss.
|
|
24
|
+
|
|
25
|
+
| One page, started fresh | Time | Peak memory |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| **Anyfetch** | **0.19 s** | **17 MB** |
|
|
28
|
+
| Headless Chromium | 1.15 s | 544 MB |
|
|
29
|
+
|
|
30
|
+
Measured on 2026-10-11 from a cloud server, with no proxy. See [how we measured](#benchmark) and how to run it again.
|
|
31
|
+
|
|
32
|
+
## What your agent gets
|
|
33
|
+
|
|
34
|
+
- **Search with no key.** Brave, Yahoo and DuckDuckGo results, with domain and date filters, quoted phrases and paging. Specialist sources for GitHub, Stack Overflow, Hacker News, arXiv and research papers. Or your own SearXNG.
|
|
35
|
+
- **Search and read in one call.** Ask for the top results together with the result list, and get the parts of each page that match your query.
|
|
36
|
+
- **Answers, not whole pages.** Give a question with the URL, and get only the parts of the page that match it. The Python 3.15 release notes are 218,000 characters; the answer to one question about them came back in 2,200.
|
|
37
|
+
- **Clean Markdown.** Links, tables and code blocks stay intact. Long pages come in parts.
|
|
38
|
+
- **PDFs.** Papers and reports come back as text, page by page.
|
|
39
|
+
- **Sites that need JavaScript.** Anyfetch reads the data inside the page, and uses the site's public API or feed for Stack Overflow, Reddit, X posts, PyPI and crates.io. No browser runs. For pages that hold nothing without their scripts, it can use Lightpanda, an optional small engine.
|
|
40
|
+
- **News and answers.** Full articles on Reuters and Bloomberg, and the answers on Quora, from the data that these sites send with the page.
|
|
41
|
+
- **Browser-grade requests.** Safari's TLS, HTTP/2 and header fingerprint. A refused fetch is retried automatically, as the same browser or as a second one.
|
|
42
|
+
- **Cloudflare checks.** When a site insists on a JavaScript check, your own Firefox passes it once. After that, Anyfetch reads the site with plain requests.
|
|
43
|
+
- **Fast on repeat.** Several pages in one call, fetched at the same time. A page fetched in the last 15 minutes comes from a local copy.
|
|
44
|
+
- **Lightweight.** A 16 MB Rust binary. No bundled browser, no JavaScript engine, no Python, no Node.
|
|
45
|
+
- **Works everywhere.** A stdio MCP server for agent harnesses, and a plain CLI for everything else.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
macOS and Linux:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
curl -fsSL https://aliasmode.github.io/anyfetch/install.sh | sh
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Windows, in PowerShell:
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
irm https://aliasmode.github.io/anyfetch/install.ps1 | iex
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The installer puts `anyfetch` in `~/.local/bin`. Then it connects Anyfetch to each agent harness that it finds on the machine: Claude Code, Codex, Gemini CLI, Hermes Agent, Pi, Cline, Amp, OpenClaw and Cursor. Start a new agent session, and the agent has `web_search`, `web_fetch` and `web_fetch_many`.
|
|
62
|
+
|
|
63
|
+
Did you install a harness later? Run `anyfetch setup`. It uses each harness's own command, tells you what it connected, and is safe to run again.
|
|
64
|
+
|
|
65
|
+
**Do you have Node.js?** Then no install is needed. Give your MCP client this server, and `npx` gets the program for your platform:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"anyfetch": { "command": "npx", "args": ["-y", "@aliasmode/anyfetch", "mcp"] }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Only Claude Code, on macOS or Linux?** You can install Anyfetch as a plugin instead. The plugin gets the program at its first start:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
claude plugin marketplace add aliasmode/anyfetch && claude plugin install anyfetch@anyfetch
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Inside Claude Code 2.1.275 or later, this is one step: `/plugin install anyfetch --marketplace aliasmode/anyfetch`. Use the plugin or the installer, not both, or the agent sees every tool twice.
|
|
82
|
+
|
|
83
|
+
## Connect your agent by hand
|
|
84
|
+
|
|
85
|
+
`anyfetch setup` does this for you. To do it by hand, each harness needs one command.
|
|
86
|
+
|
|
87
|
+
**Claude Code**
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
claude mcp add --scope user anyfetch -- anyfetch mcp
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Codex**
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
codex mcp add anyfetch -- anyfetch mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
or in `~/.codex/config.toml`:
|
|
100
|
+
|
|
101
|
+
```toml
|
|
102
|
+
[mcp_servers.anyfetch]
|
|
103
|
+
command = "anyfetch"
|
|
104
|
+
args = ["mcp"]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Hermes Agent**
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
hermes mcp add anyfetch --command anyfetch --args mcp
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Hermes connects, lists the tools and asks to enable them. Answer `Y`.
|
|
114
|
+
|
|
115
|
+
**Pi**
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
pi mcp add anyfetch -- anyfetch mcp
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Pi hides MCP tools behind its code mode by default. To show the tools to the model directly, set the exposure in `~/.pi/agent/mcp.json`:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"anyfetch": { "command": "anyfetch", "args": ["mcp"], "exposure": "direct" }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Gemini CLI**
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
gemini mcp add -s user anyfetch anyfetch mcp
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**OpenCode** — in `~/.config/opencode/opencode.json`:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"$schema": "https://opencode.ai/config.json",
|
|
142
|
+
"mcp": {
|
|
143
|
+
"anyfetch": { "type": "local", "command": ["anyfetch", "mcp"], "enabled": true }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Cursor** — in `~/.cursor/mcp.json`:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"anyfetch": { "command": "anyfetch", "args": ["mcp"] }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**More harnesses**
|
|
159
|
+
|
|
160
|
+
| Harness | Command |
|
|
161
|
+
| --- | --- |
|
|
162
|
+
| Cline | `cline mcp add anyfetch --yes -- anyfetch mcp` |
|
|
163
|
+
| Amp | `amp mcp add anyfetch -- anyfetch mcp` |
|
|
164
|
+
| OpenClaw | `openclaw mcp add anyfetch --command anyfetch --arg mcp` |
|
|
165
|
+
| Goose | `goose session --with-extension "anyfetch mcp"` |
|
|
166
|
+
| VS Code (Copilot) | `code --add-mcp "{\"name\":\"anyfetch\",\"command\":\"anyfetch\",\"args\":[\"mcp\"]}"` |
|
|
167
|
+
|
|
168
|
+
Any other MCP client: add a stdio server with the command `anyfetch` and the argument `mcp`.
|
|
169
|
+
|
|
170
|
+
Anyfetch is in the official [MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=anyfetch) as `io.github.aliasmode/anyfetch`, and on npm as [`@aliasmode/anyfetch`](https://www.npmjs.com/package/@aliasmode/anyfetch).
|
|
171
|
+
|
|
172
|
+
**No MCP?** Give the agent the CLI. Add this to `AGENTS.md` or the harness's instruction file:
|
|
173
|
+
|
|
174
|
+
```markdown
|
|
175
|
+
## Web access
|
|
176
|
+
- Search the web: `anyfetch search "<query>"`
|
|
177
|
+
- Read pages: `anyfetch fetch <url> [<url>...] --format markdown`
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Make it the default.** To have the agent use Anyfetch and not its built-in tools, turn the built-ins off:
|
|
181
|
+
|
|
182
|
+
- Claude Code, in `~/.claude/settings.json`: `"permissions": { "deny": ["WebFetch", "WebSearch"] }`
|
|
183
|
+
- Codex, in `~/.codex/config.toml`: `web_search = "disabled"`
|
|
184
|
+
|
|
185
|
+
## Use it from the command line
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
anyfetch search "rust async runtime comparison"
|
|
189
|
+
anyfetch search "tokio select" --site docs.rs --time year
|
|
190
|
+
anyfetch search "postgres vacuum freeze" --read 3
|
|
191
|
+
anyfetch search "retrieval augmented generation" --provider papers
|
|
192
|
+
anyfetch fetch https://stackoverflow.com/questions/231767 --format markdown
|
|
193
|
+
anyfetch fetch https://arxiv.org/pdf/1706.03762 --max-chars 8000 --offset 8000
|
|
194
|
+
anyfetch fetch https://docs.python.org/3.15/whatsnew/3.15.html --query "sampling profiler rate"
|
|
195
|
+
anyfetch fetch https://www.rust-lang.org/ https://go.dev/ https://ziglang.org/
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Output is JSON by default, so scripts and agents can parse it. `--format markdown` prints only the page content.
|
|
199
|
+
|
|
200
|
+
## Tools
|
|
201
|
+
|
|
202
|
+
### `web_fetch`
|
|
203
|
+
|
|
204
|
+
| Input | Meaning |
|
|
205
|
+
| --- | --- |
|
|
206
|
+
| `url` | The page to read. |
|
|
207
|
+
| `query` | Optional. A question or keywords. The result has only the parts of the page that match. |
|
|
208
|
+
| `max_chars` | Optional. The most content characters to return. The default is 50,000, or 5,000 with a `query`. |
|
|
209
|
+
| `offset` | Optional. The first content character to return. Not used with a `query`. |
|
|
210
|
+
| `fresh` | Optional. Fetch again even if a copy from the last 15 minutes exists. |
|
|
211
|
+
|
|
212
|
+
The result has `title`, `description`, `content` (Markdown), `total_chars`, `url` (after redirects), `status` and `retrieved_at`. To read a long page in parts, call again with a higher `offset` until it reaches `total_chars`. The parts come from the local copy, so the site gets one request.
|
|
213
|
+
|
|
214
|
+
With a `query`, the page is split at its paragraphs, tables and code blocks. The parts that best match the words of the query come back in page order, under their headings, with `[...]` where parts are left out. The result then has `focused: true`. A page with no matching part comes back from its start. A second question about the same page uses the local copy.
|
|
215
|
+
|
|
216
|
+
HTML becomes Markdown. A PDF becomes text with `[Page N]` marks. JSON, plain text and XML feeds come back as they are.
|
|
217
|
+
|
|
218
|
+
### `web_fetch_many`
|
|
219
|
+
|
|
220
|
+
| Input | Meaning |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| `urls` | The pages to read. They are fetched at the same time. |
|
|
223
|
+
| `query` | Optional. As for `web_fetch`. Each page gives up to 5,000 characters. |
|
|
224
|
+
| `max_chars` | Optional. The most content characters per page. By default the pages share 50,000. |
|
|
225
|
+
| `fresh` | Optional. As for `web_fetch`. |
|
|
226
|
+
|
|
227
|
+
The result has `pages`: one entry per URL, in order. Each entry is the page, or its `error`.
|
|
228
|
+
|
|
229
|
+
### `web_search`
|
|
230
|
+
|
|
231
|
+
| Input | Meaning |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `query` | The search query. Quoted phrases work. |
|
|
234
|
+
| `provider` | Optional. See the list below. The default is `auto`. |
|
|
235
|
+
| `site` | Optional. Keep results from one domain, for example `docs.rs`. |
|
|
236
|
+
| `time` | Optional. `day`, `week`, `month` or `year`. |
|
|
237
|
+
| `page` | Optional. The result page, from 1. |
|
|
238
|
+
| `read` | Optional. Also return, from this many top results, the parts of each page that match the query. |
|
|
239
|
+
| `searxng_url` | The base URL of your SearXNG instance, for the `searxng` provider. It must have JSON output on. |
|
|
240
|
+
|
|
241
|
+
Each result has `title`, `url` and `snippet`, and `content` when you set `read`.
|
|
242
|
+
|
|
243
|
+
| Provider | Source |
|
|
244
|
+
| --- | --- |
|
|
245
|
+
| `auto` | Brave, then Yahoo, then DuckDuckGo: each one when the one before gives no results. |
|
|
246
|
+
| `brave` | Brave Search. About 20 results per page. |
|
|
247
|
+
| `yahoo` | Yahoo Search. 7 results per page. No `year` filter. |
|
|
248
|
+
| `duckduckgo` | DuckDuckGo. First page only. |
|
|
249
|
+
| `searxng` | Your own SearXNG instance. |
|
|
250
|
+
| `github` | GitHub repositories, with stars and language. |
|
|
251
|
+
| `stackoverflow` | Stack Overflow questions, with score and answer count. |
|
|
252
|
+
| `hackernews` | Hacker News stories, with points and the discussion link. |
|
|
253
|
+
| `arxiv` | arXiv papers, with abstracts. |
|
|
254
|
+
| `papers` | Research papers from OpenAlex, with citation counts and open-access links. |
|
|
255
|
+
|
|
256
|
+
`site`, `time` and quoted phrases apply to the web engines. The specialist sources are free public APIs with their own request limits.
|
|
257
|
+
|
|
258
|
+
### Errors
|
|
259
|
+
|
|
260
|
+
A failed call returns an `error` object with a `code` the agent can act on:
|
|
261
|
+
|
|
262
|
+
| Code | Meaning |
|
|
263
|
+
| --- | --- |
|
|
264
|
+
| `challenge_required` | The site answered with a bot challenge that needs a browser. |
|
|
265
|
+
| `http_error` | The site refused the request. `status` has the HTTP code. |
|
|
266
|
+
| `rate_limited` | The site asked to slow down. `retry_after` has the wait, when given. |
|
|
267
|
+
| `timeout` | The site did not answer within 30 seconds. |
|
|
268
|
+
| `unsupported_content` | The URL is not text or a PDF (an image, for example). |
|
|
269
|
+
| `extraction_failed` | The page has no readable content. A scanned PDF has no text. |
|
|
270
|
+
|
|
271
|
+
## Cloudflare checks
|
|
272
|
+
|
|
273
|
+
Some sites answer every first request with a JavaScript check. Anyfetch handles it in two steps:
|
|
274
|
+
|
|
275
|
+
1. Your own Firefox passes the check once. It runs hidden, with a throwaway profile, for a few seconds.
|
|
276
|
+
2. Anyfetch saves the clearance for that site and goes back to plain requests. On Medium, one pass is good for a year.
|
|
277
|
+
|
|
278
|
+
In our test, the first page of such a site took about 5 seconds and the next one under 2 seconds.
|
|
279
|
+
|
|
280
|
+
This needs Firefox, or a Firefox-based browser, on the machine. Without one, nothing changes: the fetch returns `challenge_required`.
|
|
281
|
+
|
|
282
|
+
| Setting | Effect |
|
|
283
|
+
| --- | --- |
|
|
284
|
+
| `ANYFETCH_BROWSER=off` | Never start a browser. |
|
|
285
|
+
| `ANYFETCH_BROWSER=/path/to/browser` | Use this Firefox-based browser. |
|
|
286
|
+
|
|
287
|
+
For an MCP server, set the variable in the server entry. In Claude Code:
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
claude mcp add --scope user anyfetch -e ANYFETCH_BROWSER=off -- anyfetch mcp
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Notes:
|
|
294
|
+
|
|
295
|
+
- Tested on Linux. On Windows, and for a snap-packaged Firefox (the Ubuntu default), the browser is used only when `ANYFETCH_BROWSER` names it.
|
|
296
|
+
- A clearance belongs to the address that earned it, so the browser is not used together with a proxy.
|
|
297
|
+
- Saved clearances are in `~/.config/anyfetch/clearance/`. Delete a file to forget a site.
|
|
298
|
+
|
|
299
|
+
## Pages that need their scripts
|
|
300
|
+
|
|
301
|
+
Most pages give Anyfetch their text without JavaScript: it is in the HTML, in the page's data, or behind a public API. A few hold nothing until their scripts run. MSN, Spotify and Airbnb are examples. For those, Anyfetch can use [Lightpanda](https://github.com/lightpanda-io/browser), a small headless engine without a full browser.
|
|
302
|
+
|
|
303
|
+
Lightpanda is optional and separate. Install it from its README, put `lightpanda` on your `PATH`, and Anyfetch uses it for the pages that need it. In our test, MSN went from no content to 154,000 characters in 12 seconds, and Spotify from no content to 23,000 characters in 3 seconds. Pages that already work are not rendered, so they stay fast.
|
|
304
|
+
|
|
305
|
+
| Setting | Effect |
|
|
306
|
+
| --- | --- |
|
|
307
|
+
| `ANYFETCH_RENDERER=off` | Never start the renderer. |
|
|
308
|
+
| `ANYFETCH_RENDERER=/path/to/lightpanda` | Use this program. |
|
|
309
|
+
|
|
310
|
+
Notes:
|
|
311
|
+
|
|
312
|
+
- Lightpanda makes its own requests. It is not used together with a proxy, and a site with a bot check can refuse it.
|
|
313
|
+
- A rendered application page, such as a feed or a listing, comes back as the whole page in Markdown.
|
|
314
|
+
|
|
315
|
+
## Use a proxy
|
|
316
|
+
|
|
317
|
+
Some sites refuse cloud server addresses whatever the request looks like. If your agent runs on a server, send Anyfetch through a residential proxy. Put one line in `~/.config/anyfetch/proxy`:
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
host:port:username:password
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Anyfetch then sends every search and fetch through that HTTP proxy. The file holds the password in plain text, so keep it private: `chmod 600 ~/.config/anyfetch/proxy`. Delete the file to go direct again.
|
|
324
|
+
|
|
325
|
+
Need a proxy? [NobleProxy](https://nobleproxy.com/?utm_source=anyfetch&utm_medium=readme&utm_campaign=anyfetch) is our own service: static residential IPs that only you use, with unlimited bandwidth and HTTP support.
|
|
326
|
+
|
|
327
|
+
## What it does not do
|
|
328
|
+
|
|
329
|
+
Anyfetch itself does not run JavaScript, solve CAPTCHAs or log in. A page that shows its content only after its scripts run, with no data inside the HTML and no public API, returns its title and description unless Lightpanda is installed. It reads what a site sends to a first-time visitor. A page that needs a CAPTCHA, an account or a subscription to load stays closed, and Anyfetch says so with an error code.
|
|
330
|
+
|
|
331
|
+
Does your agent need a real browser, with logins and saved sessions? Use [AliasMode](https://aliasmode.com/use-cases/ai-agents/). It is our free, open-source antidetect browser, and it has its own MCP server for agents.
|
|
332
|
+
|
|
333
|
+
## Benchmark
|
|
334
|
+
|
|
335
|
+
The numbers at the top come from two scripts and one question set in [`bench/`](bench).
|
|
336
|
+
|
|
337
|
+
- **Pages read.** `bench/bench.py` reads each of the 97 sites in [`bench/sites.txt`](bench/sites.txt) once with each tool. A page counts as read when the tool returns at least 500 characters of text and the text is not a bot check. The same rule is applied to every tool. Anyfetch ran three times and read 73, 76 and 75 pages; the table shows the middle run. Claude Code's `WebFetch` cannot be scripted, so an agent called it once per site and recorded if real content came back.
|
|
338
|
+
- **Time and memory.** `bench/speed.py` reads 10 pages with each program, started fresh for every page, and reports the median.
|
|
339
|
+
|
|
340
|
+
- **Research questions.** [`bench/tasks.json`](bench/tasks.json) has 30 questions. Each has one exact answer and the sentence on the source page that proves it. The pages are from July to October 2026, so a model cannot answer from memory. A Claude Sonnet agent answered the questions with Anyfetch only, and again with the built-in `WebSearch` and `WebFetch` of Claude Code only. The instructions were the same: at most 8 web calls for each question, and the answer `UNKNOWN` when the tools do not give it. Anyfetch ran with no proxy, no Firefox and no Lightpanda. Each tool ran twice, and a question counts when both runs are correct.
|
|
341
|
+
|
|
342
|
+
| Question group | Anyfetch | Built-in tools |
|
|
343
|
+
| --- | --- | --- |
|
|
344
|
+
| A page on a site that blocks AI agents | 10 of 10 | 5 of 10 |
|
|
345
|
+
| A page on an open site | 10 of 10 | 10 of 10 |
|
|
346
|
+
| No URL: search first, then read | 10 of 10 | 10 of 10 |
|
|
347
|
+
|
|
348
|
+
In each single run the built-in tools answered 26 questions, but not the same 26. Three things to know about this test. The question writer used Anyfetch to check each answer, so the first group has only pages that Anyfetch can read. Four more sites on the writer's list (Reuters, Bloomberg, Financial Times and Quora) have no question, because it could not read an article page there. The site test above reads the home page of Reuters and Bloomberg, which Anyfetch can read. Since version 0.7.0, Anyfetch also reads article pages on Reuters and Bloomberg and the answers on Quora. The Financial Times needs a subscription. One Anyfetch test agent stopped after its first question, so its 5 questions were run again. Every answer is in [`bench/results/tasks.tsv`](bench/results/tasks.tsv).
|
|
349
|
+
|
|
350
|
+
The per-site results are in [`bench/results/`](bench/results). Sites change their rules often, and results differ between networks, so run it yourself:
|
|
351
|
+
|
|
352
|
+
```sh
|
|
353
|
+
python3 bench/bench.py anyfetch curl
|
|
354
|
+
pip install mcp-server-fetch && python3 bench/bench.py reference
|
|
355
|
+
python3 bench/speed.py /path/to/chromium
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Build from source
|
|
359
|
+
|
|
360
|
+
You need Rust 1.98, `cmake` and `clang` (the TLS library is BoringSSL). On Windows you also need NASM.
|
|
361
|
+
|
|
362
|
+
```sh
|
|
363
|
+
cargo install --git https://github.com/aliasmode/anyfetch
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## License
|
|
367
|
+
|
|
368
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliasmode/anyfetch",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.7.1",
|
|
4
|
+
"description": "Web search and web fetch for AI agents, with no API keys. Reads the sites that refuse AI agents.",
|
|
5
|
+
"keywords": ["mcp", "mcp-server", "web-search", "web-fetch", "ai-agents", "claude-code", "codex", "cursor"],
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"homepage": "https://github.com/aliasmode/anyfetch",
|
|
8
|
+
"repository": { "type": "git", "url": "git+https://github.com/aliasmode/anyfetch.git" },
|
|
9
|
+
"mcpName": "io.github.aliasmode/anyfetch",
|
|
10
|
+
"bin": { "anyfetch": "run.js" },
|
|
11
|
+
"files": ["run.js"],
|
|
12
|
+
"engines": { "node": ">=16" },
|
|
13
|
+
"optionalDependencies": {
|
|
14
|
+
"@aliasmode/anyfetch-darwin-arm64": "0.7.1",
|
|
15
|
+
"@aliasmode/anyfetch-darwin-x64": "0.7.1",
|
|
16
|
+
"@aliasmode/anyfetch-linux-arm64": "0.7.1",
|
|
17
|
+
"@aliasmode/anyfetch-linux-x64": "0.7.1",
|
|
18
|
+
"@aliasmode/anyfetch-win32-x64": "0.7.1"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/run.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Starts Anyfetch. npm installs the package that holds the program for this platform; this
|
|
3
|
+
// file finds it and passes the arguments on.
|
|
4
|
+
const { spawnSync } = require('node:child_process');
|
|
5
|
+
|
|
6
|
+
const platform = `${process.platform}-${process.arch}`;
|
|
7
|
+
const file = process.platform === 'win32' ? 'anyfetch.exe' : 'anyfetch';
|
|
8
|
+
let program;
|
|
9
|
+
try {
|
|
10
|
+
program = require.resolve(`@aliasmode/anyfetch-${platform}/${file}`);
|
|
11
|
+
} catch {
|
|
12
|
+
console.error(`Anyfetch has no npm package for ${platform}. See https://github.com/aliasmode/anyfetch#install`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
const result = spawnSync(program, process.argv.slice(2), { stdio: 'inherit' });
|
|
16
|
+
if (result.error) {
|
|
17
|
+
console.error(`Anyfetch could not start: ${result.error.message}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
process.exit(result.status ?? 1);
|