diff --git a/CHANGELOG.md b/CHANGELOG.md
index b797734..ffd81a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,14 +6,16 @@ Changes are tagged: **[wrapper]** for Python/JS wrapper, **[binary]** for Chromi
---
-## [Unreleased]
+## [0.6.3] — 2026-10-14
+- **[wrapper]** `geoip=True` no longer fails the launch when the exit IP's country has no locale in the map. It logs a warning and uses `en-US`. Python, JavaScript, and .NET (#591)
+- **[wrapper]** GeoIP maps Seychelles (`SC`) to the `en-SC` locale. Python, JavaScript, and .NET (#596)
- **[wrapper]** Async launches no longer freeze the caller's event loop. `launch_async()`, `launch_context_async()` and `launch_persistent_context_async()` ran the binary/license check and the GeoIP and WebRTC exit-IP lookups directly on the event loop, so every other coroutine (a server's health endpoint, WebSockets, other browsers) stalled for up to 20s per launch behind a slow proxy. They now run in a worker thread. .NET: the license check and Pro version lookup inside async launches no longer hold the caller's thread (e.g. a UI thread). Python and .NET; JavaScript was not affected.
-- **[wrapper]** Fix humanized `select_option()` raising `element is not attached to the DOM` when the pick navigates the page (e.g. a dropdown that submits its form on change). The option was selected and the page navigated, but the check after the pick ran on the new page. It now returns the chosen values, as Playwright does. A pick that lands on the wrong option without navigating still raises. Python, JavaScript Playwright, and .NET (thanks [@msamoylov](https://github.com/msamoylov), #597)
-- **[wrapper]** Humanized clicks, hovers and taps now reach a `position: fixed` element (e.g. a modal) whose DOM parent is a scrolling panel, and a `position: absolute` element that escapes a static scroller. They timed out with `element is outside of the viewport` because the scroll container was looked up through DOM parents instead of the element's containing blocks. Elements that the scroller really clips are still scrolled into view as before. Python, JavaScript, and .NET (thanks [@ccromp](https://github.com/ccromp), #593)
-- **[wrapper]** Humanized typing now matches measured human keystroke timing (Aalto 136M Keystrokes dataset): keys are held about 100 ms (was 15-35 ms); the next key often goes down before the previous one is released (rollover, about 20% of pairs); Shift is often let go before the letter key. The gap between keys depends on the keys: after a space, the same hand, the other hand, or a repeated letter. The default typing speed is about 150 ms between keys (was 70 ms). The typo rate is 4% (was 2%; 5% on `careful`). Overall typing speed stays about the same: the gaps are longer, but keys overlap. A key is never pressed again while it is still held (including the same letter in lower then upper case, as in `xX`), and every held key is released if the action fails. In .NET, a `\r\n` line break in typed text is still inserted as text, as before. `typing_delay`, `key_hold`, `shift_down_delay` and `shift_up_delay` keep their meaning. Python, JavaScript Playwright and Puppeteer, and .NET.
-- **[wrapper]** Humanized mouse moves now follow Fitts' law: a move takes longer the farther it goes, so short moves are a little slower and long moves faster than before (new `mouse_time_base`, `mouse_time_per_bit`, `mouse_time_spread`), with human run-to-run variation. Speed peaks in the first third of the move, as in recorded human strokes, not in the middle. Events are spaced at display frame rate. A move never reports zero movement, and an occasional overshoot past the target is corrected with a short second stroke. Python, JavaScript Playwright and Puppeteer, and .NET.
-- **[wrapper]** Humanized scrolling now sends whole mouse-wheel notches for the persona's platform (100 px on Windows, 40 px on macOS, 120 px on Linux), in short flicks, so a page's `deltaY` agrees with `wheelDeltaY` the way a real wheel's does. Previously it sent 20-40 px chunks with a one-notch `wheelDeltaY`, which no real wheel produces. Override the notch with the new `scroll_notch_px` setting (0 = auto). The standalone .NET `HumanScroll` helper also wheels in whole notches. **Behaviour change** (JavaScript Puppeteer): `page.mouse.wheel({ deltaY })` now scrolls a whole number of notches, at least one, so `wheel({ deltaY: 10 })` scrolls a full notch (100 px on a Windows persona). Python, JavaScript Playwright and Puppeteer, and .NET.
+- **[wrapper]** Fix humanized `select_option()` raising `element is not attached to the DOM` when the pick navigates the page (e.g. a dropdown that submits its form on change). The option was selected and the page navigated, but the check after the pick ran on the new page. It now returns the chosen values, as Playwright does. A pick that lands on the wrong option without navigating still raises. Python, JavaScript Playwright, and .NET (#597)
+- **[wrapper]** Humanized clicks, hovers and taps now reach a `position: fixed` element (e.g. a modal) whose DOM parent is a scrolling panel, and a `position: absolute` element that escapes a static scroller. They timed out with `element is outside of the viewport` because the scroll container was looked up through DOM parents instead of the element's containing blocks. Elements that the scroller really clips are still scrolled into view as before. Python, JavaScript, and .NET (#593, #595)
+- **[wrapper]** Humanized typing now matches measured human keystroke timing (Aalto 136M Keystrokes dataset): keys are held about 100 ms (was 15-35 ms); the next key often goes down before the previous one is released (rollover, about 20% of pairs); Shift is often let go before the letter key. The gap between keys depends on the keys: after a space, the same hand, the other hand, or a repeated letter. The default typing speed is about 150 ms between keys (was 70 ms). The typo rate is 4% (was 2%; 5% on `careful`). Overall typing speed stays about the same: the gaps are longer, but keys overlap. A key is never pressed again while it is still held (including the same letter in lower then upper case, as in `xX`), and every held key is released if the action fails. In .NET, a `\r\n` line break in typed text is still inserted as text, as before. `typing_delay`, `key_hold`, `shift_down_delay` and `shift_up_delay` keep their meaning. Python, JavaScript Playwright and Puppeteer, and .NET (#595)
+- **[wrapper]** Humanized mouse moves now follow Fitts' law: a move takes longer the farther it goes, so short moves are a little slower and long moves faster than before (new `mouse_time_base`, `mouse_time_per_bit`, `mouse_time_spread`), with human run-to-run variation. Speed peaks in the first third of the move, as in recorded human strokes, not in the middle. Events are spaced at display frame rate. A move never reports zero movement, and an occasional overshoot past the target is corrected with a short second stroke. Python, JavaScript Playwright and Puppeteer, and .NET (#595)
+- **[wrapper]** Humanized scrolling now sends whole mouse-wheel notches for the persona's platform (100 px on Windows, 40 px on macOS, 120 px on Linux), in short flicks, so a page's `deltaY` agrees with `wheelDeltaY` the way a real wheel's does. Previously it sent 20-40 px chunks with a one-notch `wheelDeltaY`, which no real wheel produces. Override the notch with the new `scroll_notch_px` setting (0 = auto). The standalone .NET `HumanScroll` helper also wheels in whole notches. **Behaviour change** (JavaScript Puppeteer): `page.mouse.wheel({ deltaY })` now scrolls a whole number of notches, at least one, so `wheel({ deltaY: 10 })` scrolls a full notch (100 px on a Windows persona). Python, JavaScript Playwright and Puppeteer, and .NET (#595)
- **[wrapper]** **Removed** the humanize settings `mouse_steps_divisor`, `mouse_burst_size`, `mouse_burst_pause`, `scroll_delta_base` and `scroll_delta_variance` (.NET `MouseStepsDivisor`, `MouseBurstSize`, `MouseBurstPause`, `ScrollDeltaBase`, `ScrollDeltaVariance`). Mouse moves are now timed by `mouse_time_*` and scrolling by `scroll_notch_px`, so these had no effect. A `human_config` that still passes them keeps working: Python drops them with a `FutureWarning` (shown by default and pointing at your own code), and JavaScript and the .NET override dictionary ignore them. .NET code that sets the properties directly no longer compiles.
## [0.6.2] — 2026-10-12
diff --git a/README.md b/README.md
index c78eae4..941fd0c 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ page.goto("https://example.com")
---
-## Latest: v0.6.2 — 87 source-level stealth patches (Chromium 154.0.8037.57.2)
+## Latest: v0.6.3 — 87 source-level stealth patches (Chromium 154.0.8037.57.2)
- **CloakBrowser Pro Stable** — Chromium `154.0.8037.57.2` on Linux x64 and Linux ARM64; `154.0.8037.57.1` on Windows x64 and macOS (Apple Silicon and Intel). Set a `license_key` (`licenseKey` in JS) or the `CLOAKBROWSER_LICENSE_KEY` env var and the wrapper fetches the latest Stable build for your platform automatically. See [CloakBrowser Pro](#cloakbrowser-pro)
- **.NET 8 / C# client** — CloakBrowser now ships as a NuGet package (`CloakBrowser`), mirroring the Python and JS wrappers.
@@ -724,7 +724,7 @@ Every `launch()` call sets these automatically. The **wrapper** applies platform
| Flag | Linux/Windows Default | macOS Default | Controls |
|------|--------------|---------------|----------|
-| `--fingerprint` | Random (10000–99999) | Random (10000–99999) | Master seed for canvas, WebGL, audio, fonts, client rects |
+| `--fingerprint` | Random (10000–99999) | Random (10000–99999) | Master seed for canvas, WebGL, audio, fonts |
| `--fingerprint-platform` | `windows` | `macos` | `navigator.platform`, User-Agent OS, GPU pool selection |
The binary auto-generates everything else from the seed: GPU, hardware concurrency, device memory, and screen dimensions. Each seed produces a unique, consistent fingerprint. Override with explicit flags if needed.
@@ -752,7 +752,7 @@ Supported by the binary but **not set by default** — pass via `args` to custom
| `--fingerprint-taskbar-height` | Override taskbar height (binary defaults: Win=48, Mac=95, Linux=0) |
| `--fingerprint-windows-font-metrics` | **Chromium 148+ binary only** (no-op on earlier builds). Align font metrics with the Windows platform when spoofing Windows on Linux — used in the [FingerprintJS config](#detected-by-fingerprintjs). Requires Windows fonts installed (see [Font Setup on Linux](#font-setup-on-linux)); no effect without them. On `154.0.8037.57.2` and newer this is on by default when the Windows fonts are installed, so the flag is no longer needed |
| `--fingerprint-webrtc-ip` | WebRTC ICE candidate IP replacement. Use `auto` to resolve from proxy exit IP (makes an HTTP call through the proxy), or pass an explicit IP. Auto-injected when `geoip=True` |
-| `--fingerprint-noise=false` | Disable noise injection (canvas, WebGL, audio, client rects) while keeping the deterministic fingerprint seed active |
+| `--fingerprint-noise=false` | Disable noise injection (canvas, WebGL, audio) while keeping the deterministic fingerprint seed active |
| `--fingerprint=off` | **Chromium 148+ binary only.** Pass-through debug mode — turns spoofing off and presents the machine's **real native fingerprint** (keeps only the baseline any Chrome needs). The binary strips the injected seed *and* `--fingerprint-platform`, so there's no mixed OS profile. Most useful on a genuine Windows machine to check whether an issue is our spoofing or the environment. Accepts `off`/`false`/`0`/`disable`/`disabled`. For a *pure* pass-through don't combine it with `geoip=True` / explicit timezone / locale — those stay applied. |
| `--fingerprint-allow-3p-cookies` | **Chromium 148+ binary only.** Re-enable third-party cookies for embedded flows that need them (reCAPTCHA v3, SSO, some payment challenges). Off by default; turn on only where a login/payment/embedded challenge loads but never finishes. |
| `--fingerprint-sapi-voices=false` | **Chromium 150+ binary only.** Opt out of the Windows speech-voice tables when spoofing Windows. On by default (the voice set matches a real Chrome install); turn off only if a target reacts badly to the Windows voice list. |
@@ -1038,7 +1038,7 @@ services:
**Per-connection fingerprint seeds** — run multiple browser identities from a single container. Each unique seed spawns a separate Chrome process with its own fingerprint:
```python
-# Each seed gets unique canvas noise, client rects, and other browser signals
+# Each seed gets unique canvas noise and other browser signals
b1 = pw.chromium.connect_over_cdp("http://localhost:9222?fingerprint=11111")
b2 = pw.chromium.connect_over_cdp("http://localhost:9222?fingerprint=22222")
@@ -1485,6 +1485,7 @@ Issues and PRs welcome. If something isn't working, [open an issue](https://gith
- [@bercedev](https://github.com/bercedev) — humanize support for compiled (Nuitka) Playwright builds
- [@laplace-anon](https://github.com/laplace-anon) — humanize fix for Playwright 1.64
- [@theaafofficial](https://github.com/theaafofficial) — non-blocking async launches (GeoIP, WebRTC and license lookups off the event loop)
+- [@jipeng6036-del](https://github.com/jipeng6036-del) — Seychelles GeoIP locale
## Star History
diff --git a/cloakbrowser/_version.py b/cloakbrowser/_version.py
index 22049ab..63af887 100644
--- a/cloakbrowser/_version.py
+++ b/cloakbrowser/_version.py
@@ -1 +1 @@
-__version__ = "0.6.2"
+__version__ = "0.6.3"
diff --git a/dotnet/src/CloakBrowser/CloakBrowser.csproj b/dotnet/src/CloakBrowser/CloakBrowser.csproj
index 6632198..2c9201e 100644
--- a/dotnet/src/CloakBrowser/CloakBrowser.csproj
+++ b/dotnet/src/CloakBrowser/CloakBrowser.csproj
@@ -10,7 +10,7 @@
CloakBrowser
- 0.6.2
+ 0.6.3
CloakHQ
Stealth Chromium that passes every bot detection test. Drop-in Playwright (.NET) replacement with source-level fingerprint patches.
MIT
diff --git a/dotnet/src/CloakBrowser/CloakVersion.cs b/dotnet/src/CloakBrowser/CloakVersion.cs
index 5b317a7..9fe2dd7 100644
--- a/dotnet/src/CloakBrowser/CloakVersion.cs
+++ b/dotnet/src/CloakBrowser/CloakVersion.cs
@@ -4,5 +4,5 @@ namespace CloakBrowser;
public static class CloakVersion
{
/// The CloakBrowser .NET wrapper version.
- public const string Version = "0.6.2";
+ public const string Version = "0.6.3";
}
diff --git a/js/package-lock.json b/js/package-lock.json
index 07defeb..31c6219 100644
--- a/js/package-lock.json
+++ b/js/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cloakbrowser",
- "version": "0.6.2",
+ "version": "0.6.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cloakbrowser",
- "version": "0.6.2",
+ "version": "0.6.3",
"license": "MIT",
"dependencies": {
"tar": "^7.0.0"
diff --git a/js/package.json b/js/package.json
index f0566a4..f4c90ab 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
{
"name": "cloakbrowser",
- "version": "0.6.2",
+ "version": "0.6.3",
"description": "Stealth Chromium that passes every bot detection test. Drop-in Playwright/Puppeteer replacement with source-level fingerprint patches.",
"type": "module",
"main": "dist/index.js",