@crawlee/browser 4.0.0-beta.99 → 4.0.0-rc.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/README.md CHANGED
@@ -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 16 or higher**.
37
+ > Crawlee requires **Node.js 22.13 or higher**.
38
38
 
39
39
  ### With Crawlee CLI
40
40
 
@@ -1,14 +1,25 @@
1
- import type { BasicCrawlerOptions, BasicCrawlingContext, CrawlingContext, EnqueueLinksOptions, ErrorHandler, GetUserDataFromRequest, IRequestManager, LoadedRequest, Request, RequestHandler, RouterHandler, SkippedRequestCallback } from '@crawlee/basic';
1
+ import type { AddRequestsBatchedResult, BasicCrawlerOptions, CrawlingContext, EnqueueLinksOptions, ErrorHandler, ExtractLinksOptions, GetUserDataFromRequest, LoadedRequest, CrawlingRequest, RequestHandler, RouterHandler } from '@crawlee/basic';
2
2
  import { BasicCrawler, ContextPipeline } from '@crawlee/basic';
3
- import type { BrowserController, BrowserPlugin, BrowserPoolHooks, BrowserPoolOptions, CommonPage, CrawlerRemoteBrowserOptions, InferBrowserPluginArray, LaunchContext } from '@crawlee/browser-pool';
4
- import type { Awaitable, BatchAddRequestsResult, Dictionary, IBrowserPool } from '@crawlee/types';
5
- import type { RobotsTxtFile } from '@crawlee/utils';
6
- import type { ReadonlyDeep } from 'type-fest';
7
- import type { BrowserLaunchContext } from './browser-launcher.js';
3
+ import type { CommonPage, CrawlerRemoteBrowserOptions } from '@crawlee/browser-pool';
4
+ import type { Awaitable, Dictionary, IBrowserPool } from '@crawlee/types';
5
+ import { z } from 'zod';
8
6
  interface BaseResponse {
9
7
  status(): number;
8
+ /** Optional because only Playwright and Puppeteer responses are guaranteed to carry it. */
9
+ headers?(): Record<string, string>;
10
10
  }
11
- export interface BrowserCrawlingContext<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, UserData extends Dictionary = Dictionary, GoToOptions extends Dictionary = Dictionary> extends CrawlingContext<UserData> {
11
+ /**
12
+ * The type of a browser pool the crawler builds (and therefore owns) for itself. It's an {@link IBrowserPool} that
13
+ * additionally exposes the lifecycle hooks a crawler only ever calls on a pool it created — which is why
14
+ * {@link IBrowserPool} itself intentionally omits them: `releaseAllBrowsers()` at the end of every run, and
15
+ * `destroy()` once the crawler itself is destroyed.
16
+ */
17
+ export type OwnedBrowserPool<Page> = IBrowserPool<Page> & {
18
+ releaseAllBrowsers: () => Promise<void>;
19
+ destroy: () => Promise<void>;
20
+ };
21
+ export interface BrowserCrawlingContext<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, UserData extends Dictionary = any, // with default to Dictionary we cant use a typed router in untyped crawler
22
+ GoToOptions extends Dictionary = Dictionary> extends CrawlingContext<UserData> {
12
23
  /**
13
24
  * The browser page object where the web page is loaded and rendered.
14
25
  */
@@ -16,7 +27,7 @@ export interface BrowserCrawlingContext<Page extends CommonPage = CommonPage, Re
16
27
  /**
17
28
  * The request object that was successfully loaded and navigated to, including the {@link Request.loadedUrl|`loadedUrl`} property.
18
29
  */
19
- request: LoadedRequest<Request<UserData>>;
30
+ request: LoadedRequest<CrawlingRequest<UserData>>;
20
31
  /**
21
32
  * The HTTP response object returned by the browser's navigation.
22
33
  */
@@ -26,18 +37,29 @@ export interface BrowserCrawlingContext<Page extends CommonPage = CommonPage, Re
26
37
  * object (or return `{ gotoOptions: ... }`) to influence the navigation.
27
38
  */
28
39
  gotoOptions: GoToOptions;
40
+ /**
41
+ * Extracts URLs from the current page, without adding them to the request queue.
42
+ */
43
+ extractLinks: (options?: ExtractLinksOptions) => Promise<string[]>;
29
44
  /**
30
45
  * Helper function for extracting URLs from the current page and adding them to the request queue.
31
46
  */
32
- enqueueLinks: (options?: EnqueueLinksOptions) => Promise<BatchAddRequestsResult>;
47
+ enqueueLinks: (options?: EnqueueLinksOptions) => Promise<AddRequestsBatchedResult>;
33
48
  }
34
49
  export type BrowserHook<Context = BrowserCrawlingContext, ContextExtension = {}> = (crawlingContext: Context & ContextExtension) => Awaitable<void | Partial<Context>>;
35
- export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, Context extends BrowserCrawlingContext<Page, Response, Dictionary> = BrowserCrawlingContext<Page, Response, Dictionary>, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, __BrowserPlugins extends BrowserPlugin[] = InferBrowserPluginArray<InternalBrowserPoolOptions['browserPlugins']>, __BrowserControllerReturn extends BrowserController = ReturnType<__BrowserPlugins[number]['createController']>, __LaunchContextReturn extends LaunchContext = ReturnType<__BrowserPlugins[number]['createLaunchContext']>> extends Omit<BasicCrawlerOptions<Context, ContextExtension, ExtendedContext>, 'requestHandler' | 'failedRequestHandler' | 'errorHandler'> {
36
- launchContext?: BrowserLaunchContext<any, any>;
50
+ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, Context extends BrowserCrawlingContext<Page, Response> = BrowserCrawlingContext<Page, Response>, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}> extends Omit<BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes, StatisticStateExtension>, 'requestHandler' | 'failedRequestHandler' | 'errorHandler' | 'contextPipelineBuilder'> {
37
51
  /**
38
- * An existing browser pool instance to use. When provided, the crawler will use this pool directly instead of
39
- * constructing a new one from `browserPoolOptions`, enabling browser sharing across multiple crawlers. The crawler
40
- * will not tear down a shared pool — the caller is responsible for its lifecycle.
52
+ * The browser pool the crawler should serve its pages from. This is the single way to run a pool with
53
+ * non-default options: build one with the factory that matches your crawler
54
+ * ({@link playwrightBrowserPool}, {@link puppeteerBrowserPool}, {@link stagehandBrowserPool}) - it
55
+ * accepts every {@link BrowserPoolOptions|`BrowserPool` option} and supplies the correct browser plugin
56
+ * itself, so the pool can never mismatch the crawler.
57
+ *
58
+ * A pool passed in this way is borrowed, not owned: the crawler will not tear it down, which is what makes it
59
+ * shareable across crawlers. Since the crawler then builds nothing itself, the options that configure its own
60
+ * pool (`launchContext`, `headless`, `remoteBrowser`) are rejected rather than silently ignored.
61
+ *
62
+ * When omitted, the crawler builds - and tears down - a default pool for its own browser.
41
63
  */
42
64
  browserPool?: IBrowserPool<Page>;
43
65
  /**
@@ -48,8 +70,9 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
48
70
  * crawler. Supply the connection details only: a static `endpoint` URL, a function returning one per launch,
49
71
  * or a {@link RemoteBrowserProvider}.
50
72
  *
51
- * Ignored when `browserPool` is set. For sharing a remote pool across crawlers, construct a
52
- * {@link RemoteBrowserPool} yourself and pass it as `browserPool` instead.
73
+ * Cannot be combined with `browserPool`. To tune the pool wrapping the remote connection, or to share it
74
+ * across crawlers, build it with the remote factory for your crawler ({@link remotePlaywrightBrowserPool},
75
+ * {@link remotePuppeteerBrowserPool}, {@link remoteStagehandBrowserPool}) and pass it as `browserPool`.
53
76
  */
54
77
  remoteBrowser?: CrawlerRemoteBrowserOptions;
55
78
  /**
@@ -76,7 +99,7 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
76
99
  * To make this work, we should **always**
77
100
  * let our function throw exceptions rather than catch them.
78
101
  * The exceptions are logged to the request using the
79
- * {@link Request.pushErrorMessage|`Request.pushErrorMessage()`} function.
102
+ * {@link CrawlingRequest.pushErrorMessage|`request.pushErrorMessage()`} function.
80
103
  */
81
104
  requestHandler?: RouterHandler<ExtendedContext, Routes> | RequestHandler<ExtendedContext>;
82
105
  /**
@@ -100,11 +123,6 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
100
123
  * represents the last error thrown during processing of the request.
101
124
  */
102
125
  failedRequestHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
103
- /**
104
- * Custom options passed to the underlying {@link BrowserPool} constructor.
105
- * We can tweak those to fine-tune browser management.
106
- */
107
- browserPoolOptions?: Partial<BrowserPoolOptions> & Partial<BrowserPoolHooks<__BrowserControllerReturn, __LaunchContextReturn>>;
108
126
  /**
109
127
  * Async functions that are sequentially evaluated before the navigation. Good for setting additional cookies
110
128
  * or browser properties before navigation. The function receives the `crawlingContext`; the options object
@@ -169,11 +187,6 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
169
187
  * Defines whether the cookies should be persisted for sessions. Enabled by default.
170
188
  */
171
189
  saveResponseCookies?: boolean;
172
- /**
173
- * Whether to run browser in headless mode. Defaults to `true`.
174
- * Can be also set via {@link Configuration}.
175
- */
176
- headless?: boolean | 'new' | 'old';
177
190
  /**
178
191
  * Whether to ignore custom elements (and their #shadow-roots) when processing the page content via `parseWithCheerio` helper.
179
192
  * By default, they are expanded automatically. Use this option to disable this behavior.
@@ -225,173 +238,164 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
225
238
  *
226
239
  * @category Crawlers
227
240
  */
228
- export declare abstract class BrowserCrawler<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, LaunchOptions extends Dictionary | undefined = Dictionary, Context extends BrowserCrawlingContext<Page, Response, Dictionary> = BrowserCrawlingContext<Page, Response, Dictionary>, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, GoToOptions extends Dictionary = Dictionary> extends BasicCrawler<Context, ContextExtension, ExtendedContext, Routes> {
229
- /** Backs the {@link BrowserCrawler.browserPool|`browserPool`} getter. */
230
- private browserPoolDep;
241
+ export declare abstract class BrowserCrawler<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, Context extends BrowserCrawlingContext<Page, Response> = BrowserCrawlingContext<Page, Response>, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}, GoToOptions extends Dictionary = Dictionary> extends BasicCrawler<Context, ContextExtension, ExtendedContext, Routes, StatisticStateExtension> {
242
+ #private;
231
243
  /**
232
244
  * A reference to the underlying browser pool that manages the crawler's browsers. Typed as
233
245
  * {@link IBrowserPool} so custom implementations can be plugged in via the `browserPool` constructor option.
234
246
  */
235
247
  get browserPool(): IBrowserPool<Page>;
236
- launchContext: BrowserLaunchContext<LaunchOptions, unknown>;
237
248
  protected readonly ignoreShadowRoots: boolean;
238
249
  protected readonly ignoreIframes: boolean;
239
- private readonly navigationTimeoutMillis;
240
- private readonly preNavigationHooks;
241
- private readonly postNavigationHooks;
242
- private readonly saveResponseCookies;
250
+ /**
251
+ * @internal
252
+ */
243
253
  protected static optionsShape: {
244
- // @ts-ignore optional peer dependency or compatibility with es2022
245
- navigationTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
246
- // @ts-ignore optional peer dependency or compatibility with es2022
247
- preNavigationHooks: import("ow").ArrayPredicate<unknown> & import("ow").BasePredicate<unknown[] | undefined>;
248
- // @ts-ignore optional peer dependency or compatibility with es2022
249
- postNavigationHooks: import("ow").ArrayPredicate<unknown> & import("ow").BasePredicate<unknown[] | undefined>;
250
- // @ts-ignore optional peer dependency or compatibility with es2022
251
- launchContext: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
252
- // @ts-ignore optional peer dependency or compatibility with es2022
253
- headless: import("ow").AnyPredicate<string | boolean>;
254
- // @ts-ignore optional peer dependency or compatibility with es2022
255
- browserPool: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
256
- // @ts-ignore optional peer dependency or compatibility with es2022
257
- remoteBrowser: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
258
- // @ts-ignore optional peer dependency or compatibility with es2022
259
- browserPoolOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
260
- // @ts-ignore optional peer dependency or compatibility with es2022
261
- saveResponseCookies: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
262
- // @ts-ignore optional peer dependency or compatibility with es2022
263
- proxyConfiguration: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
264
- // @ts-ignore optional peer dependency or compatibility with es2022
265
- contextPipelineBuilder: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
266
- // @ts-ignore optional peer dependency or compatibility with es2022
267
- extendContext: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
268
- // @ts-ignore optional peer dependency or compatibility with es2022
269
- requestList: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
270
- // @ts-ignore optional peer dependency or compatibility with es2022
271
- requestQueue: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
272
- // @ts-ignore optional peer dependency or compatibility with es2022
273
- requestHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
274
- // @ts-ignore optional peer dependency or compatibility with es2022
275
- requestHandlerTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
276
- // @ts-ignore optional peer dependency or compatibility with es2022
277
- errorHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
278
- // @ts-ignore optional peer dependency or compatibility with es2022
279
- failedRequestHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
280
- // @ts-ignore optional peer dependency or compatibility with es2022
281
- maxRequestRetries: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
282
- // @ts-ignore optional peer dependency or compatibility with es2022
283
- sameDomainDelaySecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
284
- // @ts-ignore optional peer dependency or compatibility with es2022
285
- maxRequestsPerCrawl: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
286
- // @ts-ignore optional peer dependency or compatibility with es2022
287
- maxCrawlDepth: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
288
- // @ts-ignore optional peer dependency or compatibility with es2022
289
- taskLoopOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
290
- // @ts-ignore optional peer dependency or compatibility with es2022
291
- concurrencySystem: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
292
- // @ts-ignore optional peer dependency or compatibility with es2022
293
- sessionPool: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
294
- // @ts-ignore optional peer dependency or compatibility with es2022
295
- statusMessageLoggingInterval: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
296
- // @ts-ignore optional peer dependency or compatibility with es2022
297
- statusMessageCallback: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
298
- // @ts-ignore optional peer dependency or compatibility with es2022
299
- additionalHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
300
- // @ts-ignore optional peer dependency or compatibility with es2022
301
- ignoreHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
302
- // @ts-ignore optional peer dependency or compatibility with es2022
303
- blockedStatusCodes: import("ow").ArrayPredicate<number>;
304
- // @ts-ignore optional peer dependency or compatibility with es2022
305
- retryOnBlocked: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
306
- // @ts-ignore optional peer dependency or compatibility with es2022
307
- respectRobotsTxtFile: import("ow").AnyPredicate<boolean | object>;
308
- // @ts-ignore optional peer dependency or compatibility with es2022
309
- onSkippedRequest: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
310
- // @ts-ignore optional peer dependency or compatibility with es2022
311
- httpClient: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
312
- // @ts-ignore optional peer dependency or compatibility with es2022
313
- configuration: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
314
- // @ts-ignore optional peer dependency or compatibility with es2022
315
- storageBackend: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
316
- // @ts-ignore optional peer dependency or compatibility with es2022
317
- eventManager: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
318
- // @ts-ignore optional peer dependency or compatibility with es2022
319
- logger: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
320
- // @ts-ignore optional peer dependency or compatibility with es2022
321
- minConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
322
- // @ts-ignore optional peer dependency or compatibility with es2022
323
- maxConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
324
- // @ts-ignore optional peer dependency or compatibility with es2022
325
- maxRequestsPerMinute: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
326
- // @ts-ignore optional peer dependency or compatibility with es2022
327
- keepAlive: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
328
- // @ts-ignore optional peer dependency or compatibility with es2022
329
- statisticsOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
330
- // @ts-ignore optional peer dependency or compatibility with es2022
331
- id: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
254
+ contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
255
+ extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
256
+ requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
257
+ requestQueue: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
258
+ requestManager: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
259
+ requestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
260
+ requestHandlerTimeoutSecs: z.ZodOptional<z.ZodCustom<number, number>>;
261
+ errorHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
262
+ failedRequestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
263
+ maxRequestRetries: z.ZodDefault<z.ZodCustom<number, number>>;
264
+ sameDomainDelaySecs: z.ZodDefault<z.ZodCustom<number, number>>;
265
+ maxRequestsPerCrawl: z.ZodOptional<z.ZodCustom<number, number>>;
266
+ maxCrawlDepth: z.ZodOptional<z.ZodCustom<number, number>>;
267
+ taskLoopOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
268
+ concurrencySystem: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
269
+ sessionPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
270
+ statusMessageLoggingInterval: z.ZodDefault<z.ZodCustom<number, number>>;
271
+ statusMessageCallback: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
272
+ additionalHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
273
+ ignoreHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
274
+ blockedStatusCodes: z.ZodOptional<z.ZodArray<z.ZodCustom<number, number>>>;
275
+ retryOnBlocked: z.ZodDefault<z.ZodBoolean>;
276
+ respectRobotsTxtFile: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCustom<Dictionary, Dictionary>]>>;
277
+ transactionalStorage: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
278
+ requestQueue: z.ZodOptional<z.ZodEnum<{
279
+ deferred: "deferred";
280
+ writeThrough: "writeThrough";
281
+ }>>;
282
+ }, z.core.$strict>]>>;
283
+ onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
284
+ // @ts-ignore optional peer dependency or compatibility with es2022
285
+ httpClient: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/http-client").BaseHttpClient>>;
286
+ // @ts-ignore optional peer dependency or compatibility with es2022
287
+ configuration: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/basic").Configuration>>;
288
+ storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
289
+ // @ts-ignore optional peer dependency or compatibility with es2022
290
+ eventManager: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/basic").EventManager>>;
291
+ logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
292
+ minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
293
+ maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
294
+ initialConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
295
+ maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
296
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
297
+ statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
298
+ id: z.ZodOptional<z.ZodString>;
299
+ navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
300
+ preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
301
+ postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
302
+ browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
303
+ browserPoolBuilder: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
304
+ remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
305
+ saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
306
+ proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
307
+ ignoreIframes: z.ZodDefault<z.ZodBoolean>;
308
+ ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
332
309
  };
310
+ /** @internal */
311
+ protected static optionsSchema: z.ZodObject<{
312
+ contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
313
+ extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
314
+ requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
315
+ requestQueue: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
316
+ requestManager: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
317
+ requestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
318
+ requestHandlerTimeoutSecs: z.ZodOptional<z.ZodCustom<number, number>>;
319
+ errorHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
320
+ failedRequestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
321
+ maxRequestRetries: z.ZodDefault<z.ZodCustom<number, number>>;
322
+ sameDomainDelaySecs: z.ZodDefault<z.ZodCustom<number, number>>;
323
+ maxRequestsPerCrawl: z.ZodOptional<z.ZodCustom<number, number>>;
324
+ maxCrawlDepth: z.ZodOptional<z.ZodCustom<number, number>>;
325
+ taskLoopOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
326
+ concurrencySystem: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
327
+ sessionPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
328
+ statusMessageLoggingInterval: z.ZodDefault<z.ZodCustom<number, number>>;
329
+ statusMessageCallback: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
330
+ additionalHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
331
+ ignoreHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
332
+ blockedStatusCodes: z.ZodOptional<z.ZodArray<z.ZodCustom<number, number>>>;
333
+ retryOnBlocked: z.ZodDefault<z.ZodBoolean>;
334
+ respectRobotsTxtFile: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCustom<Dictionary, Dictionary>]>>;
335
+ transactionalStorage: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
336
+ requestQueue: z.ZodOptional<z.ZodEnum<{
337
+ deferred: "deferred";
338
+ writeThrough: "writeThrough";
339
+ }>>;
340
+ }, z.core.$strict>]>>;
341
+ onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
342
+ // @ts-ignore optional peer dependency or compatibility with es2022
343
+ httpClient: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/http-client").BaseHttpClient>>;
344
+ // @ts-ignore optional peer dependency or compatibility with es2022
345
+ configuration: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/basic").Configuration>>;
346
+ storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
347
+ // @ts-ignore optional peer dependency or compatibility with es2022
348
+ eventManager: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/basic").EventManager>>;
349
+ logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
350
+ minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
351
+ maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
352
+ initialConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
353
+ maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
354
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
355
+ statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
356
+ id: z.ZodOptional<z.ZodString>;
357
+ navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
358
+ preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
359
+ postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
360
+ browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
361
+ browserPoolBuilder: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
362
+ remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
363
+ saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
364
+ proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
365
+ ignoreIframes: z.ZodDefault<z.ZodBoolean>;
366
+ ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
367
+ }, z.core.$strict>;
333
368
  /**
334
369
  * All `BrowserCrawler` parameters are passed via an options object.
370
+ * @internal
335
371
  */
336
- protected constructor(options: BrowserCrawlerOptions<Page, Response, Context, ContextExtension, ExtendedContext> & {
372
+ protected constructor(options: BrowserCrawlerOptions<Page, Response, Context, ContextExtension, ExtendedContext, Routes, StatisticStateExtension> & {
337
373
  contextPipelineBuilder: () => ContextPipeline<CrawlingContext, Context>;
374
+ /**
375
+ * Builds the pool the crawler owns, used only when the user injected no `browserPool`. Supplied by the
376
+ * concrete crawler, which is the only place that knows which browser plugin to run - that is also why
377
+ * `remoteBrowser` is handed to it rather than acted upon here.
378
+ */
379
+ browserPoolBuilder: (remoteBrowser?: CrawlerRemoteBrowserOptions) => OwnedBrowserPool<Page>;
338
380
  });
381
+ /** @internal */
339
382
  protected getNavigationTimeoutMillis(): number;
340
383
  protected buildContextPipeline(): ContextPipeline<CrawlingContext, BrowserCrawlingContext<Page, Response, Dictionary>>;
341
- private containsSelectors;
342
- private isRequestBlocked;
343
- private preparePage;
344
- private prepareNavigation;
345
384
  private navigate;
346
- private finalizeNavigation;
347
- /**
348
- * Copies cookies from the live browser page into the session cookie jar.
349
- */
350
- private persistCookiesFromPage;
351
385
  /**
352
386
  * Runs the user request handler, then re-reads browser cookies so login flows /
353
387
  * `page.setCookie` / XHR `Set-Cookie` updates are stored for later requests.
388
+ * @internal
354
389
  */
355
390
  protected runRequestHandler(crawlingContext: ExtendedContext): Promise<void>;
356
- private handleBlockedRequestByContent;
357
- private restoreRequestState;
358
- private applyCookies;
359
- /**
360
- * Marks session bad on navigation timeout, and stops in-flight page loading on any navigation error.
361
- */
362
- private handleNavigationTimeout;
391
+ protected abstract navigationHandler(crawlingContext: BrowserCrawlingContext<Page, Response>, gotoOptions: GoToOptions): Promise<Context['response'] | null | undefined>;
363
392
  /**
364
- * Transforms proxy-related errors to `SessionError`.
365
- */
366
- private throwIfProxyError;
367
- protected abstract _navigationHandler(crawlingContext: BrowserCrawlingContext<Page, Response>, gotoOptions: GoToOptions): Promise<Context['response'] | null | undefined>;
368
- private processResponse;
369
- /**
370
- * Function for cleaning up after all requests are processed.
371
- * @ignore
393
+ * Closes the browsers of a pool the crawler owns, so a finished run leaves none behind. The pool itself is
394
+ * crawler-lifetime and survives — destroying it here would hand a repeated `run()` a dead pool.
372
395
  */
373
396
  teardown(): Promise<void>;
397
+ destroy(): Promise<void>;
374
398
  }
375
- /** @internal */
376
- interface EnqueueLinksInternalOptions {
377
- options?: ReadonlyDeep<Omit<EnqueueLinksOptions, 'requestManager'>> & Pick<EnqueueLinksOptions, 'requestManager'>;
378
- page: CommonPage;
379
- requestManager: IRequestManager;
380
- robotsTxtFile?: RobotsTxtFile;
381
- onSkippedRequest?: SkippedRequestCallback;
382
- originalRequestUrl: string;
383
- finalRequestUrl?: string;
384
- }
385
- /** @internal */
386
- interface BoundEnqueueLinksInternalOptions {
387
- enqueueLinks: BasicCrawlingContext['enqueueLinks'];
388
- options?: ReadonlyDeep<Omit<EnqueueLinksOptions, 'requestManager'>> & Pick<EnqueueLinksOptions, 'requestManager'>;
389
- originalRequestUrl: string;
390
- finalRequestUrl?: string;
391
- page: CommonPage;
392
- }
393
- /** @internal */
394
- export declare function browserCrawlerEnqueueLinks(options: EnqueueLinksInternalOptions | BoundEnqueueLinksInternalOptions): Promise<unknown>;
395
399
  /**
396
400
  * Extracts URLs from a given page.
397
401
  * @ignore