CloakHQ/CloakBrowser · error · Error

CloakBrowser Pro: license could not be validated (server unr

Error message

CloakBrowser Pro: license could not be validated (server unreachable and no cached validation). Retry in a moment, or unset CLOAKBROWSER_LICENSE_KEY to use the free binary.

What it means

StealthWorldUnavailableError raised in _get_element_box_async (scroll_async.py:31) when page._stealth_world is None. The async humanization pipeline reads element geometry exclusively through the isolated world (no Playwright bounding_box fallback), so a missing world makes any async box read fail immediately.

Source

Thrown at js/src/download.ts:137

        if (e instanceof BinaryVerificationError) throw e;
        // Transient failure with no cached Pro binary to use — surface a clear
        // error rather than silently downloading the free binary.
        throw new Error(
          `Pro binary unavailable: ${e}. Your license is valid but the Pro ` +
            `binary could not be downloaded right now. Retry in a moment. To use ` +
            `the free binary instead, unset CLOAKBROWSER_LICENSE_KEY.`,
          { cause: e }
        );
      }
    } else if (info) {
      // Key supplied but rejected — abort, never downgrade to free.
      throw new Error(
        `CloakBrowser Pro: license key is invalid or expired (plan=${info.plan}). ` +
          `Check CLOAKBROWSER_LICENSE_KEY, or unset it to use the free binary.`,
      );
    } else {
      // Key supplied but unvalidatable (server down, no cache) — abort.
      throw new Error(
        "CloakBrowser Pro: license could not be validated (server unreachable " +
          "and no cached validation). Retry in a moment, or unset " +
          "CLOAKBROWSER_LICENSE_KEY to use the free binary.",
      );
    }
  }

  // Fail fast if no binary available for this platform
  checkPlatformAvailable();

  if (requestedVersion) {
    const binaryPath = getBinaryPath(requestedVersion);
    if (fs.existsSync(binaryPath) && isExecutable(binaryPath)) {
      showWelcome();
      return binaryPath;
    }

    console.log(

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Create the page through the stealth async launcher so _stealth_world is set before any humanized call.
  2. Check getattr(page, '_stealth_world', None) is not None before async element reads; recreate/re-attach if missing.
  3. Do not reuse page objects after their browser context has been closed.

Example fix

// before
page = await browser.new_page()  # no stealth world
box = await _get_element_box_async(page, sel)

// after
page = await stealth_context.new_page()  # _stealth_world attached
box = await _get_element_box_async(page, sel)
Defensive patterns

Strategy: validation

Validate before calling

if getattr(page, "_stealth_world", None) is None:
    raise RuntimeError("create page via stealth launcher before async humanize calls")

Type guard

def has_stealth_world(page) -> bool:
    return getattr(page, "_stealth_world", None) is not None

Try / catch

try:
    box = await _get_element_box_async(page, sel)
except StealthWorldUnavailableError:
    page = await stealth_context.new_page()
    box = await _get_element_box_async(page, sel)

Prevention

When it happens

Trigger: Calling async helpers (_get_element_box_async via _get) on a page created without stealth attach — plain browser.new_page(), a context where stealth was disabled, or after the world was torn down with the context.

Common situations: Using async cloakbrowser APIs on pages from a non-stealth launcher; mixing sync-created pages into async flows; accessing a page after browser.close(); version changes in how/when _stealth_world is attached.

Related errors


AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28). Data as JSON: /api/errors/e61cc778e4ef9d44. Report an issue: GitHub.