release: v0.3.5 — persistent context, Windows zip fix, community PRs

- Add launch_persistent_context() Python + JS with examples
- Document persistent context API in both READMEs
- Bump version to 0.3.5
- Credit @evelaa123 and @yahooguntu in CHANGELOG
This commit is contained in:
CloakHQ
2026-03-04 19:23:16 +01:00
parent de54e67f74
commit ca5cce2222
7 changed files with 122 additions and 5 deletions
+6
View File
@@ -6,6 +6,12 @@ Changes are tagged: **[wrapper]** for Python/JS wrapper, **[binary]** for Chromi
---
## [0.3.5] — 2026-03-04
- **[wrapper]** Add `launch_persistent_context()` and `launch_persistent_context_async()` (Python) — persistent browser profiles with cookie/localStorage persistence across sessions, avoids incognito detection (thanks [@evelaa123](https://github.com/evelaa123), [@yahooguntu](https://github.com/yahooguntu) — PRs #22, #17)
- **[wrapper]** Add `launchPersistentContext()` (JS/TS) — same feature for JavaScript with full type support
- **[wrapper]** Fix Windows zip extraction failure when primary download server is down — file handle leak caused `ERROR_SHARING_VIOLATION` on fallback download (thanks [@evelaa123](https://github.com/evelaa123) — PR #23)
## [0.3.4] — 2026-03-04
Binary v14: auto-spoof restored with seed, wrapper simplified to match.
+34 -2
View File
@@ -239,7 +239,7 @@ asyncio.run(main())
### `launch_context()`
Convenience function that creates browser + context with common options:
Convenience function that creates browser + context in one call with user agent, viewport, locale, and timezone:
```python
from cloakbrowser import launch_context
@@ -251,8 +251,31 @@ context = launch_context(
timezone_id="America/New_York",
)
page = context.new_page()
page.goto("https://protected-site.com")
context.close()
```
### `launch_persistent_context()`
Same as `launch_context()`, but with a persistent user profile. Cookies, localStorage, and cache persist across sessions. Also avoids incognito detection by services like BrowserScan.
```python
from cloakbrowser import launch_persistent_context
# First run — creates the profile
ctx = launch_persistent_context("./my-profile", headless=False)
page = ctx.new_page()
page.goto("https://protected-site.com")
ctx.close() # profile saved
# Next run — cookies, localStorage restored automatically
ctx = launch_persistent_context("./my-profile", headless=False)
```
Supports all the same options as `launch_context()`: `proxy`, `user_agent`, `viewport`, `locale`, `timezone_id`, `color_scheme`, `geoip`.
Async version: `launch_persistent_context_async()`.
### Utility Functions
```python
@@ -276,7 +299,7 @@ CloakBrowser ships a TypeScript package with full type definitions. Choose Playw
### Playwright (default)
```javascript
import { launch, launchContext } from 'cloakbrowser';
import { launch, launchContext, launchPersistentContext } from 'cloakbrowser';
// Basic
const browser = await launch();
@@ -298,6 +321,13 @@ const context = await launchContext({
timezoneId: 'America/New_York',
});
const page = await context.newPage();
// Persistent profile — cookies/localStorage survive restarts, avoids incognito detection
const ctx = await launchPersistentContext({
userDataDir: './chrome-profile',
headless: false,
proxy: 'http://user:pass@proxy:8080',
});
```
> **Note:** Each example above is standalone — not meant to run as one block.
@@ -452,12 +482,14 @@ The wrapper auto-downloads the correct binary for your platform.
**Python** — see [`examples/`](examples/):
- [`basic.py`](examples/basic.py) — Launch and load a page
- [`persistent_context.py`](examples/persistent_context.py) — Persistent profile with cookie/localStorage persistence
- [`recaptcha_score.py`](examples/recaptcha_score.py) — Check your reCAPTCHA v3 score
- [`stealth_test.py`](examples/stealth_test.py) — Run against all detection services
- [`fingerprint_scan_test.py`](examples/fingerprint_scan_test.py) — Test against fingerprint-scan.com and CreepJS
**JavaScript** — see [`js/examples/`](js/examples/):
- [`basic-playwright.ts`](js/examples/basic-playwright.ts) — Playwright launch and load
- [`persistent-context.ts`](js/examples/persistent-context.ts) — Persistent profile with cookie/localStorage persistence
- [`basic-puppeteer.ts`](js/examples/basic-puppeteer.ts) — Puppeteer launch and load
- [`stealth-test.ts`](js/examples/stealth-test.ts) — Full 6-site detection test suite
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.3.4"
__version__ = "0.3.5"
+29
View File
@@ -0,0 +1,29 @@
"""Persistent context example: cookies and localStorage survive across sessions."""
from cloakbrowser import launch_persistent_context
PROFILE_DIR = "./my-profile"
# Session 1 — set some state
print("=== Session 1: Setting state ===")
ctx = launch_persistent_context(PROFILE_DIR, headless=False)
page = ctx.new_page()
page.goto("https://example.com")
page.evaluate("document.cookie = 'session=abc123; path=/; max-age=3600'")
page.evaluate("localStorage.setItem('user', 'returning')")
print(f"Cookie: {page.evaluate('document.cookie')}")
ls_val = page.evaluate("localStorage.getItem('user')")
print(f"localStorage: {ls_val}")
ctx.close()
# Session 2 — state is restored
print("\n=== Session 2: Verifying persistence ===")
ctx = launch_persistent_context(PROFILE_DIR, headless=False)
page = ctx.new_page()
page.goto("https://example.com")
print(f"Cookie: {page.evaluate('document.cookie')}")
ls_val = page.evaluate("localStorage.getItem('user')")
print(f"localStorage: {ls_val}")
ctx.close()
print("\nDone!")
+11 -1
View File
@@ -60,7 +60,7 @@ await browser.close();
### Options
```javascript
import { launch, launchContext } from 'cloakbrowser';
import { launch, launchContext, launchPersistentContext } from 'cloakbrowser';
// With proxy
const browser = await launch({
@@ -94,6 +94,16 @@ const context = await launchContext({
locale: 'en-US',
timezoneId: 'America/New_York',
});
// Persistent profile — cookies/localStorage survive restarts, avoids incognito detection
const ctx = await launchPersistentContext({
userDataDir: './chrome-profile',
headless: false,
proxy: 'http://user:pass@proxy:8080',
});
const page = ctx.pages()[0] || await ctx.newPage();
await page.goto('https://example.com');
await ctx.close(); // profile saved — reuse same path to restore state
```
### Auto Timezone/Locale from Proxy IP
+40
View File
@@ -0,0 +1,40 @@
/**
* Persistent context example: cookies and localStorage survive across sessions.
*
* Usage:
* CLOAKBROWSER_BINARY_PATH=/path/to/chrome npx tsx examples/persistent-context.ts
*/
import { launchPersistentContext } from "../src/index.js";
const PROFILE_DIR = "./my-profile";
// Session 1 — set some state
console.log("=== Session 1: Setting state ===");
let ctx = await launchPersistentContext({
userDataDir: PROFILE_DIR,
headless: false,
});
let page = ctx.pages()[0] || (await ctx.newPage());
await page.goto("https://example.com");
await page.evaluate(() => {
document.cookie = "session=abc123; path=/; max-age=3600";
localStorage.setItem("user", "returning");
});
console.log(`Cookie: ${await page.evaluate(() => document.cookie)}`);
console.log(`localStorage: ${await page.evaluate(() => localStorage.getItem("user"))}`);
await ctx.close();
// Session 2 — state is restored
console.log("\n=== Session 2: Verifying persistence ===");
ctx = await launchPersistentContext({
userDataDir: PROFILE_DIR,
headless: false,
});
page = ctx.pages()[0] || (await ctx.newPage());
await page.goto("https://example.com");
console.log(`Cookie: ${await page.evaluate(() => document.cookie)}`);
console.log(`localStorage: ${await page.evaluate(() => localStorage.getItem("user"))}`);
await ctx.close();
console.log("\nDone!");
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cloakbrowser",
"version": "0.3.4",
"version": "0.3.5",
"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",