projectdiscovery/katana · error
could not initialize stealth
Error message
could not initialize stealth
What it means
createBrowserPageFunc wraps page.EvalOnNewDocument(stealth.JS) failure with this message. It means the stealth evasion JavaScript (anti-bot-detection patches) could not be registered to run on every new document of the page via the CDP Page.addScriptToEvaluateOnNewDocument call. This almost always indicates the page/browser connection is already broken, since the script itself is static and cannot be syntactically invalid at runtime.
Source
Thrown at pkg/engine/headless/browser/browser.go:463
ctx := page.GetContext()
cancelCtx, cancel := context.WithCancel(ctx)
page = page.Context(cancelCtx)
browserPage := &BrowserPage{
Page: page,
Browser: browser,
launcher: l,
cancel: cancel,
userDataDir: tempDir,
}
if err := browserPage.handlePageDialogBoxes(); err != nil {
return nil, err
}
// Add stealth evasion JS
_, err = page.EvalOnNewDocument(stealth.JS)
if err != nil {
return nil, errors.Wrap(err, "could not initialize stealth")
}
err = js.InitJavascriptEnv(page)
if err != nil {
return nil, errors.Wrap(err, "could not initialize javascript env")
}
// Success - cancel any deferred cleanup
successfulPageCreation = true
return browserPage, nil
}
// GetPageFromPool returns a page from the pool
func (l *Launcher) GetPageFromPool() (*BrowserPage, error) {
browserPage, err := l.browserPool.Get(l.createBrowserPageFunc)
if err != nil {
return nil, err
}
// TODO: should we check if the browser is alive because sometimes itView on GitHub (pinned to e3e742739c)
Solutions
- Treat this as a dead-page symptom: check the wrapped error for 'target closed' or 'context canceled' and recreate the browser/page instead of retrying EvalOnNewDocument.
- Verify the remote Chrome instance (if using ChromeWSUrl) is reachable and stable; reconnect and retry page creation.
- Reduce concurrent page creation to avoid resource exhaustion that kills Chrome mid-setup.
- Ensure Chrome and katana/rod protocol versions are compatible.
Example fix
// before: retrying setup on the same broken page
if _, err := page.EvalOnNewDocument(stealth.JS); err != nil {
// retry on same page -> keeps failing
}
// after: recreate the page when stealth init fails
if _, err := page.EvalOnNewDocument(stealth.JS); err != nil {
page.Close()
return recreatePage() // new browser page with fresh CDP session
} Defensive patterns
Strategy: try-catch
Validate before calling
if page.GetContext().Err() != nil {
// context already dead; skip stealth init and recreate the page
return recreatePage()
} Try / catch
if _, err := page.EvalOnNewDocument(stealth.JS); err != nil {
var cause error = errors.Unwrap(err)
log.Printf("stealth init failed: %v", cause)
page.Close()
return recreatePage() // a dead session cannot be reused
} Prevention
- Don't hold pages across long idle periods; create and dispose them per task.
- Check page context validity before running setup steps.
- Avoid memory pressure that kills Chrome mid-setup (limit concurrency).
- For remote Chrome, add connection health checks before page creation.
When it happens
Trigger: Calling EvalOnNewDocument after the browser/page context has died (browser crash, WebSocket disconnect, or the page context was cancelled between creation and this call), or the CDP session being invalidated before registration completes.
Common situations: Chrome crashing or being killed during page setup under heavy load; the deferred cleanup logic in createBrowserPageFunc racing with page setup when another error path closed the browser; container environments where Chrome dies quickly after launch; network/WS interruptions to a remote Chrome (ChromeWSUrl) instance.
Related errors
- could not create new page
- could not initialize javascript env
- could not enable fetch domain
- ErrNoCrawlingAction
- ErrElementNotVisible
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/b7d63949f9ae1dd8.
Report an issue: GitHub.