apify/crawlee · error

Cannot extract links because the DOM is not available.

Error message

Cannot extract links because the DOM is not available.

What it means

LinkedomCrawler's extractLinks helper needs a parsed DOM (the `window` object created from the response body) to select anchor elements and extract URLs. When the crawler did not parse the page into a linkedom window — e.g. the response was empty, non-HTML, or parsing was skipped — `crawlingContext.window` is undefined and this error is thrown instead of silently returning no links.

Source

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

                    get document(): Document {
                        throw new NavigationSkippedError(
                            'The `document` property is not available - `skipNavigation` was used',
                            { cause: err },
                        );
                    },
                };
            }

            throw err;
        }
    }

    private async addHelpers(crawlingContext: InternalHttpCrawlingContext & { body: string; window: Window }) {
        const addRequests = crawlingContext.addRequests;

        const extractLinks = async (options?: ExtractLinksOptions): Promise<string[]> => {
            if (!crawlingContext.window) {
                throw new Error('Cannot extract links because the DOM is not available.');
            }

            return extractUrlsFromWindow(
                crawlingContext.window,
                options?.selector ?? 'a',
                options?.baseUrl ?? crawlingContext.request.loadedUrl ?? crawlingContext.request.url,
            );
        };

        return {
            extractLinks,
            enqueueLinks: async (options: EnqueueLinksOptions = {}) => {
                const baseUrl = resolveBaseUrlForEnqueueLinksFiltering({
                    enqueueStrategy: options.strategy,
                    finalRequestUrl: crawlingContext.request.loadedUrl,
                    originalRequestUrl: crawlingContext.request.url,
                    userProvidedBaseUrl: options.baseUrl,
                });

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Check that the response actually returned HTML before calling extractLinks (inspect `context.response.headers['content-type']` and `context.body`).
  2. Log `context.body` in the handler to confirm a non-empty HTML document was received; skip link extraction when it is empty or non-HTML.
  3. Ensure the request succeeded (status 200) and the site is not blocking the crawler with an empty or stub response.
  4. If pages legitimately mix HTML and non-HTML responses, branch the handler: parse links only for HTML responses.

Example fix

// before
await context.extractLinks();

// after
const contentType = context.response?.headers?.['content-type'] ?? '';
if (contentType.includes('text/html')) {
    await context.extractLinks();
}
Defensive patterns

Strategy: validation

Validate before calling

const contentType = context.response?.headers?.['content-type'] ?? '';
if (!contentType.includes('text/html') || !context.body) {
    log.warning('Skipping link extraction: no HTML DOM available.');
    return;
}

Type guard

function hasDom(ctx): ctx is typeof ctx & { window: NonNullable<typeof ctx.window> } {
    return Boolean((ctx as { window?: unknown }).window);
}

Try / catch

try {
    const links = await context.extractLinks();
} catch (err) {
    if (err.message.includes('DOM is not available')) {
        log.warning('No DOM parsed; skipping link extraction.');
        return;
    }
    throw err;
}

Prevention

When it happens

Trigger: Calling `context.extractLinks()` (directly or via `enqueueLinks` behavior routed through `urls`) inside a request handler of LinkedomCrawler when `crawlingContext.window` is undefined, typically because the response body could not be parsed into a DOM.

Common situations: Crawling endpoints that return empty bodies, non-HTML content types (JSON, plain text, binary), or responses that failed to load; handlers that call extractLinks on error pages; misconfigured content-type handling that skips DOM parsing.

Related errors


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