# Why Is CloakBrowser Still Getting Blocked? 7 Source Code Fixes to Debug Detection

> CloakBrowser gets blocked by undetectable paths and untrusted events. Discover 7 source code fixes to debug detection and unblock access in this technical guide.

- Repository: [CloakHQ/CloakBrowser](https://github.com/CloakHQ/CloakBrowser)
- Tags: deep-dive
- Published: 2026-05-09

---

**CloakBrowser gets blocked when stealth layers fall back to detectable paths such as missing CDP sessions, untrusted keyboard events with `isTrusted === false`, or malformed proxy configurations that force evaluate-based injection visible to page scripts.**

CloakBrowser is an open-source automation framework designed to mask headless Chrome artifacts, yet developers often find CloakBrowser still getting blocked by advanced bot detection systems. Understanding the seven specific leak vectors in the CloakHQ/CloakBrowser source code—from CDP session failures in [`cloakbrowser/human/keyboard.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/human/keyboard.py) to proxy credential truncation—enables precise debugging and elimination of detection signals.

## Recommended Launch Configuration to Avoid Blocks

Start with this minimal safe configuration that avoids the common pitfalls described below:

```python
from cloakbrowser import launch

browser = launch(
    headless=False,                # headless=True can add minor signals; set False for debugging

    stealth_args=True,             # keep default fingerprint flags

    locale="en-US",                # passed as binary flag (--lang=en-US)

    timezone="America/New_York",   # binary flag (--fingerprint-timezone=America/New_York)

    backend="playwright",          # default – provides a CDP session

    humanize=True,                 # apply human-like mouse/keyboard patches

    human_preset="default",        # or "careful" for slower, more realistic motions

)
page = browser.new_page()
page.goto("https://bot.incolumitas.com")
browser.close()

```

*Source:* `launch` definition in [`cloakbrowser/browser.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/browser.py) (lines 54-66) and the `build_args` helper (lines 389-447).

## 1. CDP Session Failures Force Evaluate-Based Injection

When the Chrome DevTools Protocol (CDP) session is unavailable, CloakBrowser falls back to `page.evaluate` for keyboard injection. This exposes the automation script to the page context because `evaluate` runs in the isolated "stealth world" that detection scripts can fingerprint via stack inspection.

According to the CloakHQ/CloakBrowser source code, this fallback occurs in [`cloakbrowser/human/keyboard.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/human/keyboard.py) at line 75 and in [`cloakbrowser/human/keyboard_async.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/human/keyboard_async.py) at line 36. When this happens, detection patterns scanning `Error.stack` for `:302:` (the line number signature of evaluated code) trigger blocks.

To verify if your launch is leaking evaluate calls, inject this detection hook:

```python
await page.evaluate("""
    () => {
        window.__evaluateDetections = [];
        const orig = document.querySelector.bind(document);
        document.querySelector = function(sel) {
            try { throw new Error(); } catch (e) {
                if (e.stack && e.stack.includes(':302:')) {
                    window.__evaluateDetections.push(sel);
                }
            }
            return orig(sel);
        };
    }
""")

# Perform any action that might trigger a leak

await page.locator('#searchInput').click()
leaks = await page.evaluate('() => window.__evaluateDetections')
print("evaluate leaks:", leaks)   # Should be []

```

If the array contains entries, the fallback path was taken. Ensure you use a backend that provides a CDP session (`playwright` or `patchright`) and that no network issue blocks CDP creation.

## 2. Untrusted Keyboard Events (isTrusted === false)

Before issue #110, the human keyboard shim generated synthetic `KeyboardEvent` objects via `page.evaluate`, resulting in `event.isTrusted === false`. Sites checking this property reject the input as automated.

This logic resides in [`cloakbrowser/human/keyboard.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/human/keyboard.py) (line 75) and determines whether to use CDP or evaluate. To verify trusted event generation, type a shift-symbol and inspect the window properties:

```python
await page.evaluate("""
    () => {
        window.__untrustedKeys = []; window.__trustedKeys = [];
        const inp = document.querySelector('#searchInput');
        inp.addEventListener('keydown', e => {
            (e.isTrusted ? window.__trustedKeys : window.__untrustedKeys).push(e.key);
        }, true);
    }
""")
await page.locator('#searchInput').click()
await page.keyboard.type('test!')
untrusted = await page.evaluate('() => window.__untrustedKeys')
trusted   = await page.evaluate('() => window.__trustedKeys')
print('untrusted:', untrusted)   # Should not contain '!'

print('trusted:',   trusted)     # Should contain '!'

```

Upgrade to `v0.6.x` or later and ensure `humanize=True` is set without custom config that disables the CDP path.

## 3. Locale and Timezone Set via CDP Instead of Binary Flags

Passing `locale` or `timezone` as Playwright context kwargs forces CDP-based `Emulation.setLocale` calls, which are detectable. The library deliberately sets these via binary flags only (`--lang` and `--fingerprint-timezone`).

In [`cloakbrowser/browser.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/browser.py), the `launch*` functions (lines 81-85) and helper `build_args` (lines 389-447) handle this. Always provide these values through function arguments so they become binary flags, not CDP commands.

Verify your launch arguments include:

- `--lang=en-US`
- `--fingerprint-timezone=America/New_York`

If these are missing from the Chrome args but the locale is still set, the values are being applied via CDP and will be caught by detection scripts.

## 4. Malformed Proxy URLs Cause SOCKS5 Credential Truncation

Malformed proxy URLs lead Chromium to drop password characters (e.g., `=`), causing proxy rejection and fallback to less-stealthy modes. The normalization logic is in `_resolve_proxy_config` (lines 334-360) and `_normalize_socks_string_url` (lines 211-219).

Use URL-encoded credentials:

```python
browser = launch(
    proxy="socks5://user:pa%3Dss@host:1080"  # encode special characters like '='

)

```

Or let the library normalize the string automatically.

## 5. Missing or Outdated Stealth Flags

The default stealth arguments from `get_default_stealth_args` are inserted only when `stealth_args=True`. Disabling them launches vanilla Chromium with detectable fingerprints.

In `build_args` (lines 389-447), the `stealth_args` flag gates insertion of default fingerprint flags. Keep `stealth_args=True` (the default). If you need custom flags, merge them with `get_default_stealth_args()` rather than replacing the list.

## 6. Incorrect Backend Selection (patchright vs playwright)

The `patchright` backend suppresses CDP signals (helpful for some reCAPTCHA v3 challenges) but breaks proxy authentication and `add_init_script`. Incorrect backend choice silently forces fallback to detectable paths.

The resolution logic is in `_resolve_backend` (lines 177-183). Use the default `playwright` backend unless specifically required. Set `CLOAKBROWSER_BACKEND=playwright` or pass `backend="playwright"` to `launch` to ensure CDP session availability.

## 7. Human-Behaviour Patch Not Applied

The `humanize` flag must be enabled to replace default Playwright keyboard and mouse actions with stealth implementations. Without it, the browser uses original Playwright implementations that lack trusted event generation.

The `launch*` functions (lines 39-45) call `patch_browser` or `patch_browser_async` only when `humanize=True`. Set this flag and optionally tune the preset:

```python
browser = launch(
    humanize=True,
    human_preset="careful"  # slower, more realistic motions

)

```

## Debugging Workflow: Six Steps to Isolate Detection Leaks

When CloakBrowser is still getting blocked, follow this systematic workflow to identify the exact vector:

1. **Run the built-in stealth test script**. The [`examples/stealth_test.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/examples/stealth_test.py) file exercises live detection services (Botscan, Bot.incolumitas, Fingerprint Scan).

   ```bash
   python -m examples.stealth_test
   ```

   Review the pass/fail matrix; any "blocked" row indicates an active signal.

2. **Inject the evaluate detection hook** as shown in the CDP section above to catch `:302:` stack traces.

3. **Verify keyboard event trust** using the shift-symbol test to confirm `isTrusted` flags.

4. **Inspect the Chromium command line** via debug logs. Enable logging to see the final argument list:

   ```python
   import logging
   logging.basicConfig(level=logging.DEBUG)
   ```

   Look for `--lang`, `--fingerprint-timezone`, and properly escaped proxy credentials.

5. **Confirm the CDP session** exists by checking `browser._connection` after launch. If `None`, the backend failed to create a session, forcing fallback paths.

6. **Re-run unit tests** with `pytest -k stealth` after each configuration change to ensure detection hooks remain clean.

## Summary

- **CDP session availability** determines whether keyboard injection uses stealth CDP or detectable evaluate calls in [`cloakbrowser/human/keyboard.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/cloakbrowser/human/keyboard.py).
- **Trusted events** require `humanize=True` and version `v0.6.x`+ to avoid `isTrusted === false` detection.
- **Binary flags** (`--lang`, `--fingerprint-timezone`) are stealthier than CDP emulation calls set via context kwargs.
- **Proxy URLs** must be URL-encoded to prevent credential truncation in `_resolve_proxy_config`.
- **Stealth arguments** must remain enabled via `stealth_args=True` and merged rather than replaced.
- **Backend selection** should default to `playwright` unless specific `patchright` features are required.
- **Debugging workflow** relies on the built-in [`stealth_test.py`](https://github.com/CloakHQ/CloakBrowser/blob/main/stealth_test.py), detection hooks, and CDP session verification.

## Frequently Asked Questions

### Why does CloakBrowser pass some sites but fail others?

Different sites employ distinct detection vectors. One site may check `event.isTrusted` while another scans for CDP emissions. Use the evaluate detection hook and keyboard trust tests to identify which specific signal the failing site detects, then verify the corresponding configuration (CDP session, humanize flags, or locale settings) is correctly applied.

### How do I verify that CDP is actually working and not falling back to evaluate?

Check `browser._connection` after launching; if it is `None`, no CDP session exists. Additionally, inject the stack-scanning hook that watches for `:302:` in `Error.stack`. If `window.__evaluateDetections` contains entries after interaction, the fallback path was taken, indicating CDP failure.

### Should I use patchright or playwright as the backend?

Use `playwright` (the default) unless you specifically need to suppress CDP signals for reCAPTCHA v3 challenges. The `patchright` backend breaks proxy authentication and `add_init_script`, which can force detectable fallback behavior. Set `backend="playwright"` explicitly if unsure.

### What is the correct way to set locale and timezone to avoid detection?

Always pass `locale` and `timezone` as arguments to `launch()`, not as Playwright context options. This ensures CloakBrowser sets them via binary flags (`--lang` and `--fingerprint-timezone`) rather than detectable CDP `Emulation.setLocale` calls. Verify these flags appear in the debug logs.