minifetch-api 1.3.4 → 1.4.0
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/README.md +28 -18
- package/dist/esm/client.js +8 -4
- package/dist/esm/utils/payment.js +20 -2
- package/dist/types/client.d.ts +8 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,19 +5,17 @@
|
|
|
5
5
|
</a>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
|
-
**[Minifetch](https://minifetch.com) is a hosted toolkit of extraction primitives
|
|
8
|
+
**[Minifetch](https://minifetch.com) is a hosted toolkit of web page extraction primitives.** Run them as a full technical SEO audit or call one at a time for a fraction of the price — and a fraction of the LLM tokens. No subscription.
|
|
9
9
|
|
|
10
10
|
- ✅ **Always pay-per-fetch at competitive prices.**
|
|
11
11
|
- ✅ [Sign up](https://minifetch.com/dashboard) for an account & get free starter credits. 🎉🎉
|
|
12
12
|
- ⛔ No charge for blocked pages (403 errors).
|
|
13
13
|
|
|
14
14
|
---
|
|
15
|
+
|
|
15
16
|
**👉 [Full API docs](https://minifetch.com/docs/api) | [LLMs.txt](https://minifetch.com/llms.txt) and [SKILL.md](https://minifetch.com/SKILL.md) for agents | Questions? Join our [Discord](https://discord.gg/EM6ET8Dshm)**
|
|
16
17
|
|
|
17
18
|
---
|
|
18
|
-
**Payments.** Two ways to pay:
|
|
19
|
-
1. Credit card + API key. Get started free - [visit our dashboard to Sign Up](https://minifetch.com/dashboard). Create a Minifetch account and it will be auto-loaded with 25 free technical SEO page audits. Top up with your credit card later.
|
|
20
|
-
2. USDC on Base or Solana. Just load your wallet with USDC, you're ready. No "gas token" (ETH or SOL) required. You don't need a Minifetch account either, just load your wallet and go!
|
|
21
19
|
|
|
22
20
|
## Prerequisites
|
|
23
21
|
|
|
@@ -25,9 +23,15 @@
|
|
|
25
23
|
- A valid API key from our [dashboard](https://minifetch.com/dashboard)
|
|
26
24
|
- ***Or*** an Ethereum or Solana private key for making USDC payments on Base or Solana networks.
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
**Payments.** Two ways to pay:
|
|
27
|
+
1. Credit card + API key. Get started free - [visit our dashboard to Sign Up](https://minifetch.com/dashboard). Create a Minifetch account and it will be auto-loaded with 25 free technical SEO page audits. Top up with your credit card later.
|
|
28
|
+
2. USDC on Base or Solana. Just load your wallet with USDC, you're ready. No "gas token" (ETH or SOL) required. You don't need a Minifetch account either, just load your wallet and go!
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
## Install
|
|
31
|
+
Add to your project:
|
|
32
|
+
```
|
|
33
|
+
npm install minifetch-api --save`
|
|
34
|
+
```
|
|
31
35
|
|
|
32
36
|
## Quick Start
|
|
33
37
|
|
|
@@ -66,7 +70,7 @@ try {
|
|
|
66
70
|
|
|
67
71
|
After the Quick Start, you have the following methods to use.
|
|
68
72
|
|
|
69
|
-
**Wrap** these methods in a **try/catch** just like in the Quick Start example above. **Code examples** can be also found in the [Github repository](https://github.com/Niche-Networks/minifetch-api/)
|
|
73
|
+
**Wrap** these methods in a **try/catch** just like in the Quick Start example above. **Code examples** can be also found in the [Github repository /example- directories](https://github.com/Niche-Networks/minifetch-api/).
|
|
70
74
|
|
|
71
75
|
The `checkAndExtract` methods check the target URL's `robots.txt` file to ensure its not blocked and tell us your preferred crawl delay (defaults to 1 second between requests to your domain). So fetching 10 URLs takes at least 10 seconds to complete by default. This is by design, so Minifetch never hammers your server or slows it down for your real users. If the URL is blocked, read [How To Unblock Minifetch](https://minifetch.com/tutorials/unblock-minifetch).
|
|
72
76
|
|
|
@@ -82,15 +86,15 @@ await client.checkAndRunSeoPageAudit(url);
|
|
|
82
86
|
|
|
83
87
|
await client.checkAndExtractUrlMetadata(url, options);
|
|
84
88
|
// Price: $0.002
|
|
85
|
-
// Extracts rich structured metadata from your URL:
|
|
86
|
-
// description, canonical, SEO-related meta tags, Open Graph and
|
|
87
|
-
// Twitter card tags, JSON-LD and more.
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
// and
|
|
91
|
-
// drop-in replacement for the npm `url-metadata` package.
|
|
89
|
+
// Extracts rich structured metadata from your URL: redirects, favicons,
|
|
90
|
+
// title, description, canonical, SEO-related meta tags, Open Graph and
|
|
91
|
+
// Twitter card tags, JSON-LD and more. Returns everything by default;
|
|
92
|
+
// narrow the response with the `fields` query param (pass atomic field
|
|
93
|
+
// names, ex: ?fields=title,description or the named groups: network,meta,
|
|
94
|
+
// og,twitter and/or meta:<name> for a specific page meta tag)
|
|
92
95
|
// Options:
|
|
93
|
-
// {
|
|
96
|
+
// { fields: ['canonical', 'og:url'] } - narrows to custom selected fields
|
|
97
|
+
// { omitEmpty: true } - defaults to false
|
|
94
98
|
// { includeResponseBody: true } - defaults to false
|
|
95
99
|
|
|
96
100
|
await client.checkAndExtractUrlLinks(url);
|
|
@@ -125,10 +129,14 @@ await client.extractUrlLinks(url);
|
|
|
125
129
|
await client.extractUrlPreview(url);
|
|
126
130
|
await client.extractUrlContent(url, options); // same options as above
|
|
127
131
|
```
|
|
132
|
+
|
|
128
133
|
---
|
|
134
|
+
|
|
129
135
|
### Error Types
|
|
130
|
-
When you wrap the functions above in a try/catch, here are the errors you may encounter. You are never charged for URLs that are blocked or error.
|
|
136
|
+
When you wrap the functions above in a try/catch, here are some of the errors you may encounter. You are never charged for URLs that are blocked or error.
|
|
131
137
|
|
|
138
|
+
- **"InvalidURLError: Invalid url ${url}"**
|
|
139
|
+
- The URL is malformed in some way, correct it and try again.
|
|
132
140
|
- **"RobotsBlockedError: URL is blocked by robots.txt"**
|
|
133
141
|
- Minifetch is explicitly blocked by the website's `robots.txt`, cannot be fetched. If this is your site, read our tutorial [How To Unblock Minifetch](https://minifetch.com/tutorials/unblock-minifetch)
|
|
134
142
|
- **"Network Error: 402 Payment Required"**
|
|
@@ -139,9 +147,9 @@ When you wrap the functions above in a try/catch, here are the errors you may en
|
|
|
139
147
|
- URLs that pass their robots.txt check but are blocked anyway via 403 or other tactics may error like this. No charge.
|
|
140
148
|
- **"503 Service Temporarily Unavailable"**
|
|
141
149
|
- Likely encountering upstream timeout errors on the target URL.
|
|
142
|
-
|
|
143
|
-
- The URL is malformed in some way, correct it and try again.
|
|
150
|
+
|
|
144
151
|
---
|
|
152
|
+
|
|
145
153
|
### Service Limitations
|
|
146
154
|
Minifetch only extracts publicly available metadata and content from pages accessible without authentication and javascript execution.
|
|
147
155
|
|
|
@@ -156,6 +164,7 @@ What Minifetch does NOT do *currently* but may offer in the future as an add-on:
|
|
|
156
164
|
- Access authenticated or logged-in content
|
|
157
165
|
|
|
158
166
|
---
|
|
167
|
+
|
|
159
168
|
### USDC Best Practices
|
|
160
169
|
- Uses the [x402 Protocol](https://www.x402.org/). No "gas token" (ETH or SOL) required, just load your wallet with USDC on Base or Solana network.
|
|
161
170
|
- LLMs & Agents should *never* have direct access to your private key. They *will* expose it!
|
|
@@ -164,6 +173,7 @@ What Minifetch does NOT do *currently* but may offer in the future as an add-on:
|
|
|
164
173
|
- Pass your private key into the Minifetch API Client with an [environment variable](https://developer.vonage.com/en/blog/how-to-use-environment-variables-in-javascript-with-dotenv).
|
|
165
174
|
|
|
166
175
|
---
|
|
176
|
+
|
|
167
177
|
**License**
|
|
168
178
|
|
|
169
179
|
MIT / Copyright (c) 2026 Lauren Garcia
|
package/dist/esm/client.js
CHANGED
|
@@ -67,7 +67,8 @@ export class MinifetchClient {
|
|
|
67
67
|
*
|
|
68
68
|
* @param url
|
|
69
69
|
* @param options
|
|
70
|
-
* @param options.
|
|
70
|
+
* @param options.fields
|
|
71
|
+
* @param options.omitEmpty
|
|
71
72
|
* @param options.includeResponseBody
|
|
72
73
|
* @throws {InvalidUrlError} if URL is invalid
|
|
73
74
|
* @throws {ExtractionFailedError} various reasons, check README
|
|
@@ -78,8 +79,10 @@ export class MinifetchClient {
|
|
|
78
79
|
try {
|
|
79
80
|
const normalizedUrl = validateAndNormalizeUrl(url);
|
|
80
81
|
const params = new URLSearchParams({ url: normalizedUrl });
|
|
81
|
-
if (options?.
|
|
82
|
-
params.set("
|
|
82
|
+
if (options?.fields?.length)
|
|
83
|
+
params.set("fields", options.fields.join(","));
|
|
84
|
+
if (options?.omitEmpty)
|
|
85
|
+
params.set("omitEmpty", "true");
|
|
83
86
|
if (options?.includeResponseBody)
|
|
84
87
|
params.set("includeResponseBody", "true");
|
|
85
88
|
const requestUrl = `${this.baseUrl}${this._paidPath("/extract/url-metadata")}?${params.toString()}`;
|
|
@@ -167,7 +170,8 @@ export class MinifetchClient {
|
|
|
167
170
|
*
|
|
168
171
|
* @param url
|
|
169
172
|
* @param options
|
|
170
|
-
* @param options.
|
|
173
|
+
* @param options.fields
|
|
174
|
+
* @param options.omitEmpty
|
|
171
175
|
* @param options.includeResponseBody
|
|
172
176
|
*/
|
|
173
177
|
async checkAndExtractUrlMetadata(url, options) {
|
|
@@ -42,7 +42,8 @@ export async function handlePayment(url, config) {
|
|
|
42
42
|
const fetchWithPayment = wrapFetchWithPayment(fetch, _x402Client);
|
|
43
43
|
const response = await fetchWithPayment(url, { method: "GET" });
|
|
44
44
|
if (!response.ok) {
|
|
45
|
-
|
|
45
|
+
const serverMessage = await readServerErrorMessage(response);
|
|
46
|
+
throw new NetworkError(`Request failed: ${response.status} ${response.statusText}${serverMessage ? ` — ${serverMessage}` : ""}`);
|
|
46
47
|
}
|
|
47
48
|
const httpClient = new x402HTTPClient(_x402Client);
|
|
48
49
|
const paymentResponse = httpClient.getPaymentSettleResponse(name => response.headers.get(name));
|
|
@@ -79,7 +80,8 @@ export async function handleApiKeyRequest(url, config) {
|
|
|
79
80
|
},
|
|
80
81
|
});
|
|
81
82
|
if (!response.ok) {
|
|
82
|
-
|
|
83
|
+
const serverMessage = await readServerErrorMessage(response);
|
|
84
|
+
throw new NetworkError(`Request failed: ${response.status} ${response.statusText}${serverMessage ? ` — ${serverMessage}` : ""}`);
|
|
83
85
|
}
|
|
84
86
|
return { response };
|
|
85
87
|
}
|
|
@@ -101,3 +103,19 @@ function getExplorerLink(config, txHash) {
|
|
|
101
103
|
return "";
|
|
102
104
|
}
|
|
103
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Best-effort read of the rich server error message from a non-ok response.
|
|
108
|
+
* Minifetch error bodies carry it at results[0].error.message.
|
|
109
|
+
*
|
|
110
|
+
* @param response - non-ok Response (body is consumed)
|
|
111
|
+
*/
|
|
112
|
+
async function readServerErrorMessage(response) {
|
|
113
|
+
try {
|
|
114
|
+
const body = (await response.json());
|
|
115
|
+
// TODO: revisit this approach when we scale up to multiple results per request
|
|
116
|
+
return body?.results?.[0]?.error?.message;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
package/dist/types/client.d.ts
CHANGED
|
@@ -36,7 +36,8 @@ export declare class MinifetchClient {
|
|
|
36
36
|
*
|
|
37
37
|
* @param url
|
|
38
38
|
* @param options
|
|
39
|
-
* @param options.
|
|
39
|
+
* @param options.fields
|
|
40
|
+
* @param options.omitEmpty
|
|
40
41
|
* @param options.includeResponseBody
|
|
41
42
|
* @throws {InvalidUrlError} if URL is invalid
|
|
42
43
|
* @throws {ExtractionFailedError} various reasons, check README
|
|
@@ -44,7 +45,8 @@ export declare class MinifetchClient {
|
|
|
44
45
|
* @throws {NetworkError} various reasons, check README
|
|
45
46
|
*/
|
|
46
47
|
extractUrlMetadata(url: string, options?: {
|
|
47
|
-
|
|
48
|
+
fields?: string[];
|
|
49
|
+
omitEmpty?: boolean;
|
|
48
50
|
includeResponseBody?: boolean;
|
|
49
51
|
}): Promise<PaidEndpointResponse>;
|
|
50
52
|
/**
|
|
@@ -94,11 +96,13 @@ export declare class MinifetchClient {
|
|
|
94
96
|
*
|
|
95
97
|
* @param url
|
|
96
98
|
* @param options
|
|
97
|
-
* @param options.
|
|
99
|
+
* @param options.fields
|
|
100
|
+
* @param options.omitEmpty
|
|
98
101
|
* @param options.includeResponseBody
|
|
99
102
|
*/
|
|
100
103
|
checkAndExtractUrlMetadata(url: string, options?: {
|
|
101
|
-
|
|
104
|
+
fields?: string[];
|
|
105
|
+
omitEmpty?: boolean;
|
|
102
106
|
includeResponseBody?: boolean;
|
|
103
107
|
}): Promise<PaidEndpointResponse>;
|
|
104
108
|
/**
|
package/package.json
CHANGED