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 it

View on GitHub (pinned to e3e742739c)

Solutions

  1. 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.
  2. Verify the remote Chrome instance (if using ChromeWSUrl) is reachable and stable; reconnect and retry page creation.
  3. Reduce concurrent page creation to avoid resource exhaustion that kills Chrome mid-setup.
  4. 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

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


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/b7d63949f9ae1dd8. Report an issue: GitHub.