apify/crawlee · error · NavigationSkippedError

The `window` property is not available - `skipNavigation` wa

Error message

The `window` property is not available - `skipNavigation` was used

What it means

LinkedomCrawler mirrors JSDOMCrawler's skipNavigation design: with navigation skipped, no parse5/linkedom window is built, and the `window` property getter throws NavigationSkippedError to signal that DOM access is not possible in this mode.

Source

Thrown at packages/linkedom-crawler/src/internals/linkedom-crawler.ts:248

                crawlingContext.body.toString(),
                isXml ? 'text/xml' : 'text/html',
            );

            return {
                window: document.defaultView,
                get body() {
                    return document.documentElement.outerHTML;
                },
                get document() {
                    // See comment about typing in LinkeDOMCrawlingContext definition
                    return document as unknown as Document;
                },
            };
        } catch (err) {
            if (err instanceof NavigationSkippedError) {
                return {
                    get window(): Window {
                        throw new NavigationSkippedError(
                            'The `window` property is not available - `skipNavigation` was used',
                            { cause: err },
                        );
                    },
                    get body(): string {
                        throw new NavigationSkippedError(
                            'The `body` property is not available - `skipNavigation` was used',
                            { cause: err },
                        );
                    },
                    get document(): Document {
                        throw new NavigationSkippedError(
                            'The `document` property is not available - `skipNavigation` was used',
                            { cause: err },
                        );
                    },
                };
            }

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Remove `skipNavigation: true` if DOM/window access is needed.
  2. Use `context.body` (raw string) and parse with cheerio or regex instead.
  3. Branch the handler based on navigation-skip state before touching `window`.
  4. Use extractLinks only on requests where the window was actually created.

Example fix

// before (skipNavigation: true)
const links = [...context.window.document.querySelectorAll('a')];

// after
const $ = (await import('cheerio')).load(context.body);
const links = $('a[href]').toArray();
Defensive patterns

Strategy: try-catch

Validate before calling

if (request.skipNavigation === true) {
    // context.window will throw; use cheerio on context.body instead
}

Type guard

function isNavigationSkippedError(err: unknown): err is Error & { name: 'NavigationSkippedError' } {
    return err instanceof Error && err.name === 'NavigationSkippedError';
}

Try / catch

try {
    const { window } = context;
    parse(window);
} catch (err) {
    if ((err as Error).message.includes('`skipNavigation` was used')) {
        parseCheerio(context.body);
    } else {
        throw err;
    }
}

Prevention

When it happens

Trigger: Using LinkedomCrawler with `skipNavigation: true` and then reading `context.window` in the requestHandler.

Common situations: Performance-tuned linkedom crawls with skipNavigation but handlers that still call window-based helpers (enqueueLinks, extractLinks); handlers shared between linkedom and normal crawlers.

Related errors


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/9b4691d0345ee6f9. Report an issue: GitHub.