@crawlee/impit-client 4.0.0-beta.25 → 4.0.0-beta.251
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 +15 -15
- package/index.d.ts +10 -12
- package/index.js +79 -13
- package/package.json +10 -8
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<a href="https://crawlee.dev">
|
|
3
3
|
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true"
|
|
5
|
-
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500"
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true" />
|
|
5
|
+
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500" />
|
|
6
6
|
</picture>
|
|
7
7
|
</a>
|
|
8
|
-
<br
|
|
8
|
+
<br />
|
|
9
9
|
<small>A web scraping and browser automation library</small>
|
|
10
10
|
</h1>
|
|
11
11
|
|
|
12
|
-
<p align=center>
|
|
13
|
-
<a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift"
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift" width="250" height="55"/></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
<p align=center>
|
|
17
|
-
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg"
|
|
18
|
-
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg"
|
|
19
|
-
<a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord"
|
|
20
|
-
<a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status"
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg" /></a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg" /></a>
|
|
19
|
+
<a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord" /></a>
|
|
20
|
+
<a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status" /></a>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
Crawlee covers your crawling and scraping end-to-end and **helps you build reliable scrapers. Fast.**
|
|
@@ -34,7 +34,7 @@ Crawlee is available as the [`crawlee`](https://www.npmjs.com/package/crawlee) N
|
|
|
34
34
|
|
|
35
35
|
We recommend visiting the [Introduction tutorial](https://crawlee.dev/js/docs/introduction) in Crawlee documentation for more information.
|
|
36
36
|
|
|
37
|
-
> Crawlee requires **Node.js
|
|
37
|
+
> Crawlee requires **Node.js 22.13 or higher**.
|
|
38
38
|
|
|
39
39
|
### With Crawlee CLI
|
|
40
40
|
|
|
@@ -89,7 +89,7 @@ By default, Crawlee stores data to `./storage` in the current working directory.
|
|
|
89
89
|
We provide automated beta builds for every merged code change in Crawlee. You can find them in the npm [list of releases](https://www.npmjs.com/package/crawlee?activeTab=versions). If you want to test new features or bug fixes before we release them, feel free to install a beta build like this:
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
npm install crawlee@
|
|
92
|
+
npm install crawlee@next
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need to specify dependency overrides in your `package.json` file so that you don't end up with multiple versions of Crawlee installed:
|
|
@@ -98,9 +98,9 @@ If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need
|
|
|
98
98
|
{
|
|
99
99
|
"overrides": {
|
|
100
100
|
"apify": {
|
|
101
|
-
"@crawlee/core": "
|
|
102
|
-
"@crawlee/types": "
|
|
103
|
-
"@crawlee/utils": "
|
|
101
|
+
"@crawlee/core": "$crawlee",
|
|
102
|
+
"@crawlee/types": "$crawlee",
|
|
103
|
+
"@crawlee/utils": "$crawlee"
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import type { CustomFetchOptions } from '@crawlee/http-client';
|
|
2
2
|
import { BaseHttpClient } from '@crawlee/http-client';
|
|
3
|
+
import type { CrawleeLogger } from '@crawlee/types';
|
|
3
4
|
import { type ImpitOptions } from 'impit';
|
|
4
5
|
export declare const Browser: {
|
|
5
|
-
readonly Chrome:
|
|
6
|
-
readonly Firefox:
|
|
6
|
+
readonly Chrome: 'chrome';
|
|
7
|
+
readonly Firefox: 'firefox';
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
10
|
* A HTTP client implementation based on the `impit` library.
|
|
10
11
|
*/
|
|
11
12
|
export declare class ImpitHttpClient extends BaseHttpClient {
|
|
12
|
-
private
|
|
13
|
+
#private;
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
* This is useful for performance reasons, as creating
|
|
16
|
-
* a new client for each request breaks TCP connection
|
|
17
|
-
* (and other resources) reuse.
|
|
15
|
+
* @param options.cacheClients Whether to cache `impit` clients between requests. Defaults to `true`.
|
|
18
16
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
constructor(options?: Omit<ImpitOptions, 'proxyUrl' | 'timeout'> & {
|
|
18
|
+
cacheClients?: boolean;
|
|
19
|
+
logger?: CrawleeLogger;
|
|
20
|
+
});
|
|
22
21
|
/**
|
|
23
22
|
* @inheritDoc
|
|
24
23
|
*/
|
|
25
|
-
fetch(request: Request, options?: RequestInit & CustomFetchOptions): Promise<Response>;
|
|
24
|
+
protected fetch(request: Request, options?: RequestInit & CustomFetchOptions): Promise<Response>;
|
|
26
25
|
}
|
|
27
|
-
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
+
import { serviceLocator } from '@crawlee/core';
|
|
1
2
|
import { BaseHttpClient, ResponseWithUrl } from '@crawlee/http-client';
|
|
2
3
|
import { Impit } from 'impit';
|
|
3
4
|
import { LruCache } from '@apify/datastructures';
|
|
5
|
+
// Concrete impit impersonation profiles per browser family. The plain `chrome` /
|
|
6
|
+
// `firefox` aliases fall back to the oldest available version, which is a
|
|
7
|
+
// fingerprint giveaway — we pick one of these explicitly instead. Keep in sync
|
|
8
|
+
// with impit's `Browser` type when bumping the dependency.
|
|
9
|
+
const IMPIT_VERSIONS_BY_BROWSER = {
|
|
10
|
+
chrome: [
|
|
11
|
+
'chrome100',
|
|
12
|
+
'chrome101',
|
|
13
|
+
'chrome104',
|
|
14
|
+
'chrome107',
|
|
15
|
+
'chrome110',
|
|
16
|
+
'chrome116',
|
|
17
|
+
'chrome124',
|
|
18
|
+
'chrome125',
|
|
19
|
+
'chrome131',
|
|
20
|
+
'chrome136',
|
|
21
|
+
'chrome142',
|
|
22
|
+
],
|
|
23
|
+
firefox: ['firefox128', 'firefox133', 'firefox135', 'firefox144'],
|
|
24
|
+
};
|
|
4
25
|
export const Browser = {
|
|
5
26
|
'Chrome': 'chrome',
|
|
6
27
|
'Firefox': 'firefox',
|
|
@@ -9,42 +30,87 @@ export const Browser = {
|
|
|
9
30
|
* A HTTP client implementation based on the `impit` library.
|
|
10
31
|
*/
|
|
11
32
|
export class ImpitHttpClient extends BaseHttpClient {
|
|
12
|
-
impitOptions;
|
|
33
|
+
#impitOptions;
|
|
34
|
+
#cacheClients;
|
|
13
35
|
/**
|
|
14
36
|
* Enables reuse of `impit` clients for the same set of options.
|
|
15
37
|
* This is useful for performance reasons, as creating
|
|
16
38
|
* a new client for each request breaks TCP connection
|
|
17
39
|
* (and other resources) reuse.
|
|
18
40
|
*/
|
|
19
|
-
clientCache = new LruCache({ maxLength: 10 });
|
|
20
|
-
|
|
41
|
+
#clientCache = new LruCache({ maxLength: 10 });
|
|
42
|
+
/**
|
|
43
|
+
* Stable impit impersonation version per fingerprint object, so the same
|
|
44
|
+
* session keeps impersonating the same browser version across requests
|
|
45
|
+
* instead of rerolling on every call.
|
|
46
|
+
*/
|
|
47
|
+
#impitBrowserByFingerprint = new WeakMap();
|
|
48
|
+
#getClient(options) {
|
|
49
|
+
if (!this.#cacheClients) {
|
|
50
|
+
return new Impit(options);
|
|
51
|
+
}
|
|
21
52
|
const { cookieJar, ...rest } = options;
|
|
22
53
|
const cacheKey = JSON.stringify(rest);
|
|
23
|
-
const existingClient = this
|
|
54
|
+
const existingClient = this.#clientCache.get(cacheKey);
|
|
24
55
|
if (existingClient && (!cookieJar || existingClient.cookieJar === cookieJar)) {
|
|
25
56
|
return existingClient.client;
|
|
26
57
|
}
|
|
27
58
|
const client = new Impit(options);
|
|
28
|
-
this
|
|
59
|
+
this.#clientCache.add(cacheKey, { client, cookieJar: cookieJar });
|
|
29
60
|
return client;
|
|
30
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* @param options.cacheClients Whether to cache `impit` clients between requests. Defaults to `true`.
|
|
64
|
+
*/
|
|
31
65
|
constructor(options) {
|
|
32
|
-
super();
|
|
33
|
-
|
|
66
|
+
super({ logger: options?.logger });
|
|
67
|
+
const { cacheClients = true, logger, ...impitOptions } = options ?? {};
|
|
68
|
+
if (impitOptions.browser) {
|
|
69
|
+
(logger ?? serviceLocator.getLogger()).warningOnce('The `browser` option of ImpitHttpClient overrides the browser fingerprint of the session. ' +
|
|
70
|
+
'Using it with Crawlee crawlers can lead to incompatible Session setups.');
|
|
71
|
+
}
|
|
72
|
+
this.#impitOptions = impitOptions;
|
|
73
|
+
this.#cacheClients = cacheClients;
|
|
34
74
|
}
|
|
35
75
|
/**
|
|
36
76
|
* @inheritDoc
|
|
37
77
|
*/
|
|
38
78
|
async fetch(request, options) {
|
|
39
|
-
const { proxyUrl, redirect, signal } = options ?? {};
|
|
40
|
-
const
|
|
41
|
-
|
|
79
|
+
const { proxyUrl, redirect, signal, fingerprint, ignoreTlsErrors } = options ?? {};
|
|
80
|
+
const impitBrowser = this.#impitOptions.browser ? undefined : this.#resolveImpitBrowser(fingerprint);
|
|
81
|
+
const impit = this.#getClient({
|
|
82
|
+
...this.#impitOptions,
|
|
83
|
+
...(impitBrowser ? { browser: impitBrowser } : {}),
|
|
84
|
+
// The per-request flag (from the crawler option or a MITM proxy session)
|
|
85
|
+
// can only enable ignoring, never override a constructor-level `true`.
|
|
86
|
+
...(ignoreTlsErrors ? { ignoreTlsErrors: true } : {}),
|
|
42
87
|
proxyUrl,
|
|
43
88
|
followRedirects: redirect === 'follow',
|
|
44
89
|
});
|
|
45
|
-
|
|
90
|
+
// The caller's signal carries the deadline (for crawlers, the navigation window that `extendTimeout()` can
|
|
91
|
+
// push out), so impit's 30 s default must not cut the request short. Without a signal, the default stays.
|
|
92
|
+
const response = await impit.fetch(request, {
|
|
93
|
+
signal: signal ?? undefined,
|
|
94
|
+
...(signal ? { timeout: null } : {}),
|
|
95
|
+
});
|
|
96
|
+
// Once the headers are in, an aborted signal only stops impit's body reads, while the download itself keeps
|
|
97
|
+
// going. Piping the body through the signal cancels the download too.
|
|
98
|
+
const body = signal && response.body ? response.body.pipeThrough(new TransformStream(), { signal }) : response.body;
|
|
46
99
|
// todo - cast shouldn't be needed here, impit returns `Uint8Array`
|
|
47
|
-
return new ResponseWithUrl(
|
|
100
|
+
return new ResponseWithUrl(body, response);
|
|
101
|
+
}
|
|
102
|
+
#resolveImpitBrowser(fingerprint) {
|
|
103
|
+
if (!fingerprint?.browser)
|
|
104
|
+
return undefined;
|
|
105
|
+
const cached = this.#impitBrowserByFingerprint.get(fingerprint);
|
|
106
|
+
if (cached)
|
|
107
|
+
return cached;
|
|
108
|
+
// impit can only impersonate Chrome and Firefox. Map other (Chromium-based or
|
|
109
|
+
// unsupported) families like `edge`/`safari` onto Chrome so the request still
|
|
110
|
+
// carries realistic browser headers instead of impit's bare `*/*` defaults.
|
|
111
|
+
const versions = IMPIT_VERSIONS_BY_BROWSER[fingerprint.browser] ?? IMPIT_VERSIONS_BY_BROWSER.chrome;
|
|
112
|
+
const picked = versions[Math.floor(Math.random() * versions.length)];
|
|
113
|
+
this.#impitBrowserByFingerprint.set(fingerprint, picked);
|
|
114
|
+
return picked;
|
|
48
115
|
}
|
|
49
116
|
}
|
|
50
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/impit-client",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.251",
|
|
4
4
|
"description": "impit-based HTTP client implementation for Crawlee. Impersonates browser requests to avoid bot detection.",
|
|
5
5
|
"engines": {
|
|
6
|
-
"node": ">=22.
|
|
6
|
+
"node": ">=22.13.0"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://crawlee.dev",
|
|
40
40
|
"scripts": {
|
|
41
|
-
"build": "
|
|
41
|
+
"build": "pnpm clean && pnpm compile && pnpm copy",
|
|
42
42
|
"clean": "rimraf ./dist",
|
|
43
43
|
"compile": "tsc -p tsconfig.build.json",
|
|
44
44
|
"copy": "tsx ../../scripts/copy.ts"
|
|
@@ -47,10 +47,12 @@
|
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@apify/datastructures": "^
|
|
51
|
-
"@crawlee/
|
|
52
|
-
"
|
|
53
|
-
"
|
|
50
|
+
"@apify/datastructures": "^3.0.1",
|
|
51
|
+
"@crawlee/core": "4.0.0-beta.251",
|
|
52
|
+
"@crawlee/http-client": "4.0.0-beta.251",
|
|
53
|
+
"@crawlee/types": "4.0.0-beta.251",
|
|
54
|
+
"impit": "^0.14.8",
|
|
55
|
+
"tough-cookie": "^6.0.2"
|
|
54
56
|
},
|
|
55
57
|
"lerna": {
|
|
56
58
|
"command": {
|
|
@@ -59,5 +61,5 @@
|
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
},
|
|
62
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "e8a0d8a538fabf624c73b6354dbf7194882300a5"
|
|
63
65
|
}
|
package/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAKjD,eAAO,MAAM,OAAO;;;CAGV,CAAC;AAEX;;GAEG;AACH,qBAAa,eAAgB,SAAQ,cAAc;IAC/C,OAAO,CAAC,YAAY,CAAe;IAEnC;;;;;OAKG;IACH,OAAO,CAAC,WAAW,CAA2F;IAE9G,OAAO,CAAC,SAAS;gBAgBL,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;IAKhE;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAc/F"}
|
package/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,KAAK,EAAqB,MAAM,OAAO,CAAC;AAGjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,OAAO,GAAG;IACnB,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,SAAS;CACd,CAAC;AAEX;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,cAAc;IACvC,YAAY,CAAe;IAEnC;;;;;OAKG;IACK,WAAW,GAA2D,IAAI,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAEtG,SAAS,CAAC,OAAqB;QACnC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEtD,IAAI,cAAc,IAAI,CAAC,CAAC,SAAS,IAAI,cAAc,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,CAAC;YAC3E,OAAO,cAAc,CAAC,MAAM,CAAC;QACjC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAA2B,EAAE,CAAC,CAAC;QAEnF,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,YAAY,OAAoD;QAC5D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,OAAO,IAAI,EAAE,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,OAA0C;QACpE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAErD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;YACzB,GAAG,IAAI,CAAC,YAAY;YACpB,QAAQ;YACR,eAAe,EAAE,QAAQ,KAAK,QAAQ;SACzC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QAE7E,mEAAmE;QACnE,OAAO,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;CACJ"}
|