apify/crawlee · error · NavigationSkippedError
The `waitForSelector` method is not available - `skipNavigat
Error message
The `waitForSelector` method is not available - `skipNavigation` was used
What it means
NavigationSkippedError thrown by the getter for `waitForSelector` on the crawling context. `waitForSelector` is a browser/DOM API and meaningless without navigation, so it is disabled for `skipNavigation` requests.
Source
Thrown at packages/http-crawler/src/internals/http-crawler.ts:572
if (crawlingContext.request.skipNavigation) {
return {
get contentType(): InternalHttpCrawlingContext['contentType'] {
throw new NavigationSkippedError(
'The `contentType` property is not available - `skipNavigation` was used',
);
},
get body(): InternalHttpCrawlingContext['body'] {
throw new NavigationSkippedError(
'The `body` property is not available - `skipNavigation` was used',
);
},
get json(): InternalHttpCrawlingContext['json'] {
throw new NavigationSkippedError(
'The `json` property is not available - `skipNavigation` was used',
);
},
get waitForSelector(): InternalHttpCrawlingContext['waitForSelector'] {
throw new NavigationSkippedError(
'The `waitForSelector` method is not available - `skipNavigation` was used',
);
},
get parseWithCheerio(): InternalHttpCrawlingContext['parseWithCheerio'] {
throw new NavigationSkippedError(
'The `parseWithCheerio` method is not available - `skipNavigation` was used',
);
},
};
}
tryCancel();
// Before `parseResponse`, which throws for error status codes - a 429 the user opted into treating as an
// error is still a rate limit the domain should back off from.
if (crawlingContext.response.status === 429) {
const retryAfter = crawlingContext.response.headers.get('retry-after');
if (this.recordDomainRateLimit(crawlingContext.request.url, retryAfter)) {View on GitHub (pinned to dbe57fb09c)
Solutions
- Remove `waitForSelector` calls from HTTP handlers or guard them behind `!request.skipNavigation`.
- Use plain parsing of `context.body` after a real navigation instead.
- Route skipped requests to handlers without DOM helpers.
Example fix
// before
await context.waitForSelector('.item');
// after
if (!context.request.skipNavigation) { await context.waitForSelector('.item'); } Defensive patterns
Strategy: type-guard
Validate before calling
if (!request.skipNavigation && typeof ctx.waitForSelector === 'function') { await ctx.waitForSelector(sel); } Type guard
function supportsDomWait(ctx: CrawlingContext): boolean { return !(ctx.request as any).skipNavigation; } Try / catch
try { await ctx.waitForSelector(sel); } catch (err) { if (err instanceof NavigationSkippedError) { /* skip DOM wait for HTTP-only context */ } else throw err; } Prevention
- Remove DOM waits from pure HTTP handlers.
- Guard browser-only helpers behind crawler type checks.
- Share parsing logic, not navigation logic, between crawler types.
- Test handlers with skipNavigation requests in CI.
When it happens
Trigger: Calling `context.waitForSelector(...)` in a handler for a `skipNavigation: true` request (typically in code shared with a browser crawler).
Common situations: Porting Playwright/CheerioCrawler-style handlers to HttpCrawler with skipNavigation seeds; copy-pasted handlers including DOM waits that never apply to plain HTTP.
Related errors
- The `request.loadedUrl` property is not available - `skipNav
- The `response` property is not available - `skipNavigation`
- The `contentType` property is not available - `skipNavigatio
- The `body` property is not available - `skipNavigation` was
- The `json` property is not available - `skipNavigation` was
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/9a7854f82d5bbd00.
Report an issue: GitHub.