clearcote 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,6 +52,22 @@ const browser = await launch({
52
52
  });
53
53
  ```
54
54
 
55
+ ### Auto geo-match (`geoip`)
56
+
57
+ Set `geoip: true` and Clearcote resolves the **proxy's exit IP** (looked up *through* the proxy) and auto-fills any unset `timezone`, `acceptLanguage`, and `location` so they match the proxy's region — no manual timezone/locale bookkeeping:
58
+
59
+ ```ts
60
+ const browser = await launch({
61
+ fingerprint: "user-7423",
62
+ proxy: { server: "http://host:8080", username: "u", password: "p" },
63
+ geoip: true, // timezone + navigator.languages/Accept-Language auto-set from the proxy's geo
64
+ });
65
+ ```
66
+
67
+ Anything you set explicitly wins over `geoip`. With no proxy it uses your direct connection's IP. The lookup needs an **http(s) proxy** — SOCKS proxies are skipped (set `timezone`/`acceptLanguage` yourself).
68
+
69
+ Geo data comes from the offline [geoip-all-in-one](https://github.com/daijro/geoip-all-in-one) MaxMind database (downloaded + cached on first use; GPL-3.0 data, the same source Camoufox uses) — more accurate than a single online API — with `ip-api.com` as a fallback.
70
+
55
71
  ### Persistent profile
56
72
 
57
73
  ```ts
@@ -80,8 +96,10 @@ All optional. Anything not listed here is passed straight through to Playwright
80
96
  | `hardwareConcurrency` | `--fingerprint-hardware-concurrency` | `navigator.hardwareConcurrency`. |
81
97
  | `location` | `--fingerprint-location` | `"lat,lng"` (only when geo permission is granted). |
82
98
  | `timezone` | `--timezone` | IANA timezone, e.g. `America/New_York`. |
99
+ | `acceptLanguage` | `--accept-lang` | `navigator.languages` + `Accept-Language` header, e.g. `en-US,en`. |
83
100
  | `webrtcIp` | `--webrtc-ip` | WebRTC egress IP to report (your proxy IP). |
84
101
  | `disableGpuFingerprint` | `--disable-gpu-fingerprint` | Turn off GPU/WebGL spoofing. |
102
+ | `geoip` | _(directive)_ | `true` → resolve the proxy's exit-IP geo and auto-fill timezone/acceptLanguage/location. |
85
103
 
86
104
  ## API
87
105
 
@@ -23,6 +23,12 @@ export interface FingerprintOptions {
23
23
  location?: string;
24
24
  /** IANA timezone, e.g. "America/New_York". */
25
25
  timezone?: string;
26
+ /**
27
+ * Accept-Language / navigator.languages, e.g. "en-US,en". Sets BOTH the server-side
28
+ * Accept-Language header and navigator.language(s) coherently (Chromium `--accept-lang`).
29
+ * Set this to match the timezone/proxy region — or let `geoip` fill it automatically.
30
+ */
31
+ acceptLanguage?: string;
26
32
  /** WebRTC egress IP to report (typically your proxy's public IP). */
27
33
  webrtcIp?: string;
28
34
  /** Turn OFF GPU/WebGL fingerprint spoofing (advertise the real backend). */
@@ -33,6 +39,10 @@ export declare function splitFingerprintOptions<T extends FingerprintOptions>(op
33
39
  fingerprint: FingerprintOptions;
34
40
  rest: Omit<T, keyof FingerprintOptions>;
35
41
  };
42
+ /** Normalize an Accept-Language value for Chromium's `--accept-lang`: a plain comma-separated
43
+ * tag list with NO `;q=` weights or spaces (Chromium adds the q-weights to the header itself; a
44
+ * `;` in the switch value trips a DCHECK and crashes the renderer). */
45
+ export declare function cleanAcceptLanguage(v: string): string;
36
46
  /** Build the Chromium switches for a set of fingerprint options. */
37
47
  export declare function fingerprintArgs(o: FingerprintOptions): string[];
38
48
  //# sourceMappingURL=fingerprint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACzC,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChE,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAiBD,6FAA6F;AAC7F,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,kBAAkB,EAClE,OAAO,EAAE,CAAC,GACT;IAAE,WAAW,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,kBAAkB,CAAC,CAAA;CAAE,CAW9E;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAoB/D"}
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACzC,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChE,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAkBD,6FAA6F;AAC7F,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,kBAAkB,EAClE,OAAO,EAAE,CAAC,GACT;IAAE,WAAW,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,kBAAkB,CAAC,CAAA;CAAE,CAW9E;AAED;;uEAEuE;AACvE,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAqB/D"}
@@ -11,6 +11,7 @@ const FINGERPRINT_KEYS = [
11
11
  "hardwareConcurrency",
12
12
  "location",
13
13
  "timezone",
14
+ "acceptLanguage",
14
15
  "webrtcIp",
15
16
  "disableGpuFingerprint",
16
17
  ];
@@ -28,6 +29,16 @@ export function splitFingerprintOptions(options) {
28
29
  }
29
30
  return { fingerprint, rest: rest };
30
31
  }
32
+ /** Normalize an Accept-Language value for Chromium's `--accept-lang`: a plain comma-separated
33
+ * tag list with NO `;q=` weights or spaces (Chromium adds the q-weights to the header itself; a
34
+ * `;` in the switch value trips a DCHECK and crashes the renderer). */
35
+ export function cleanAcceptLanguage(v) {
36
+ return String(v)
37
+ .split(",")
38
+ .map((t) => t.split(";")[0].trim())
39
+ .filter(Boolean)
40
+ .join(",");
41
+ }
31
42
  /** Build the Chromium switches for a set of fingerprint options. */
32
43
  export function fingerprintArgs(o) {
33
44
  const args = [];
@@ -46,6 +57,8 @@ export function fingerprintArgs(o) {
46
57
  set("fingerprint-hardware-concurrency", o.hardwareConcurrency);
47
58
  set("fingerprint-location", o.location);
48
59
  set("timezone", o.timezone);
60
+ if (o.acceptLanguage)
61
+ args.push(`--accept-lang=${cleanAcceptLanguage(String(o.acceptLanguage))}`);
49
62
  set("webrtc-ip", o.webrtcIp);
50
63
  if (o.disableGpuFingerprint)
51
64
  args.push("--disable-gpu-fingerprint");
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,+GAA+G;AAiC/G,MAAM,gBAAgB,GAAiC;IACrD,aAAa;IACb,UAAU;IACV,iBAAiB;IACjB,OAAO;IACP,cAAc;IACd,WAAW;IACX,aAAa;IACb,qBAAqB;IACrB,UAAU;IACV,UAAU;IACV,UAAU;IACV,uBAAuB;CACxB,CAAC;AAEF,6FAA6F;AAC7F,MAAM,UAAU,uBAAuB,CACrC,OAAU;IAEV,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAK,gBAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,WAAuC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAyC,EAAE,CAAC;AAC1E,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,CAAqB;IACnD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,KAAc,EAAE,EAAE;QAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;IACF,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IAClC,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;IACvD,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAClC,GAAG,CAAC,2BAA2B,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACjD,GAAG,CAAC,wBAAwB,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3C,GAAG,CAAC,0BAA0B,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IAC/C,GAAG,CAAC,kCAAkC,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/D,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5B,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,qBAAqB;QAAE,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,+GAA+G;AAuC/G,MAAM,gBAAgB,GAAiC;IACrD,aAAa;IACb,UAAU;IACV,iBAAiB;IACjB,OAAO;IACP,cAAc;IACd,WAAW;IACX,aAAa;IACb,qBAAqB;IACrB,UAAU;IACV,UAAU;IACV,gBAAgB;IAChB,UAAU;IACV,uBAAuB;CACxB,CAAC;AAEF,6FAA6F;AAC7F,MAAM,UAAU,uBAAuB,CACrC,OAAU;IAEV,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAK,gBAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,WAAuC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAyC,EAAE,CAAC;AAC1E,CAAC;AAED;;uEAEuE;AACvE,MAAM,UAAU,mBAAmB,CAAC,CAAS;IAC3C,OAAO,MAAM,CAAC,CAAC,CAAC;SACb,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SAClC,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,CAAqB;IACnD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,KAAc,EAAE,EAAE;QAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;IACF,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IAClC,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;IACvD,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAClC,GAAG,CAAC,2BAA2B,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACjD,GAAG,CAAC,wBAAwB,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3C,GAAG,CAAC,0BAA0B,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IAC/C,GAAG,CAAC,kCAAkC,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/D,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,cAAc;QAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAClG,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,qBAAqB;QAAE,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface Geo {
2
+ ip?: string;
3
+ country?: string;
4
+ timezone?: string;
5
+ acceptLanguage?: string;
6
+ location?: string;
7
+ }
8
+ /**
9
+ * Resolve geo for the egress (through `proxy` if given, else direct). Never throws — returns null
10
+ * on failure. Uses the geoip-all-in-one offline DB first, ip-api.com as a fallback.
11
+ */
12
+ export declare function resolveGeo(proxy?: {
13
+ server?: string;
14
+ username?: string;
15
+ password?: string;
16
+ }, opts?: {
17
+ quiet?: boolean;
18
+ }): Promise<Geo | null>;
19
+ export declare function acceptLanguageForCountry(cc?: string): string;
20
+ //# sourceMappingURL=geoip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geoip.d.ts","sourceRoot":"","sources":["../src/geoip.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,GAAG;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiLD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,KAAK,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EACjE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAWrB;AAqBD,wBAAgB,wBAAwB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5D"}
package/dist/geoip.js ADDED
@@ -0,0 +1,252 @@
1
+ // geoip: resolve the egress IP's geo (timezone + lat/lon + language) so the browser matches the
2
+ // proxy actually in use — the way Camoufox does it. Primary source is daijro's offline
3
+ // "geoip-all-in-one" MaxMind DB (more accurate than a single online API; merges IP2Location +
4
+ // GeoLite2 + DB-IP, timezone computed from coordinates). Flow: discover the exit IP via a small
5
+ // IP-echo *through the proxy*, then look that IP up in the cached .mmdb. Falls back to ip-api.com
6
+ // (direct geo through the proxy) if the DB can't be fetched/opened.
7
+ //
8
+ // The .mmdb (GPL-3.0 data) is downloaded + cached on first use (≈52 MB zip → ≈120 MB), NOT bundled.
9
+ // http(s) proxies only for the lookup; SOCKS is skipped (we never fall back to the local IP under a
10
+ // proxy, which would give the wrong region).
11
+ import http from "node:http";
12
+ import { createWriteStream, existsSync, mkdirSync, readdirSync, rmSync, statSync } from "node:fs";
13
+ import os from "node:os";
14
+ import path from "node:path";
15
+ import { Readable } from "node:stream";
16
+ import { pipeline } from "node:stream/promises";
17
+ import extract from "extract-zip";
18
+ import maxmind from "maxmind";
19
+ const MMDB_URL = "https://github.com/daijro/geoip-all-in-one/releases/latest/download/geoip-aio-all.mmdb.zip";
20
+ const MMDB_MAX_AGE_DAYS = 30;
21
+ const IPECHO_URLS = ["http://api.ipify.org", "http://ip-api.com/line/?fields=query"];
22
+ const IPAPI_URL = "http://ip-api.com/json/?fields=status,message,countryCode,timezone,lat,lon,query";
23
+ function log(quiet, m) {
24
+ if (!quiet)
25
+ process.stderr.write(`[clearcote] ${m}\n`);
26
+ }
27
+ function geoCacheRoot() {
28
+ if (process.env.CLEARCOTE_CACHE)
29
+ return path.join(process.env.CLEARCOTE_CACHE, "geoip");
30
+ if (process.platform === "win32")
31
+ return path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "clearcote", "geoip");
32
+ if (process.platform === "darwin")
33
+ return path.join(os.homedir(), "Library", "Caches", "clearcote", "geoip");
34
+ return path.join(process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache"), "clearcote", "geoip");
35
+ }
36
+ function proxyUrl(proxy) {
37
+ if (!proxy?.server)
38
+ return null;
39
+ let server = proxy.server;
40
+ if (!/:\/\//.test(server))
41
+ server = "http://" + server;
42
+ if (proxy.username) {
43
+ const u = new URL(server);
44
+ u.username = encodeURIComponent(proxy.username);
45
+ if (proxy.password)
46
+ u.password = encodeURIComponent(proxy.password);
47
+ return u.toString();
48
+ }
49
+ return server;
50
+ }
51
+ function isSocks(proxy) {
52
+ return !!proxy?.server && /^socks/i.test(proxy.server);
53
+ }
54
+ // GET an http:// URL, optionally through an http proxy (absolute-form request target). Text body.
55
+ function httpGetText(targetUrl, proxy, timeoutMs) {
56
+ return new Promise((resolve, reject) => {
57
+ const t = new URL(targetUrl);
58
+ let opts;
59
+ if (proxy) {
60
+ const p = new URL(proxy);
61
+ opts = { host: p.hostname, port: p.port || 80, path: targetUrl, timeout: timeoutMs,
62
+ headers: { Host: t.host, "User-Agent": "clearcote-sdk", Accept: "*/*" } };
63
+ if (p.username) {
64
+ const cred = Buffer.from(`${decodeURIComponent(p.username)}:${decodeURIComponent(p.password)}`).toString("base64");
65
+ opts.headers["Proxy-Authorization"] = `Basic ${cred}`;
66
+ }
67
+ }
68
+ else {
69
+ opts = { host: t.hostname, port: t.port || 80, path: t.pathname + t.search, timeout: timeoutMs,
70
+ headers: { Host: t.host, "User-Agent": "clearcote-sdk", Accept: "*/*" } };
71
+ }
72
+ const req = http.request(opts, (res) => {
73
+ let data = "";
74
+ res.setEncoding("utf8");
75
+ res.on("data", (c) => (data += c));
76
+ res.on("end", () => resolve(data.trim()));
77
+ });
78
+ req.on("error", reject);
79
+ req.on("timeout", () => req.destroy(new Error("timed out")));
80
+ req.end();
81
+ });
82
+ }
83
+ const IPV4 = /^(?:\d{1,3}\.){3}\d{1,3}$/;
84
+ const IPV6 = /^[0-9a-f:]+$/i;
85
+ function looksLikeIp(s) {
86
+ return IPV4.test(s) || (s.includes(":") && IPV6.test(s));
87
+ }
88
+ /** Discover the egress IP via an IP-echo through the proxy (or direct). */
89
+ async function exitIp(proxy, quiet) {
90
+ for (const url of IPECHO_URLS) {
91
+ try {
92
+ const ip = (await httpGetText(url, proxy, 8000)).split(/\s+/)[0];
93
+ if (looksLikeIp(ip))
94
+ return ip;
95
+ }
96
+ catch {
97
+ /* try next */
98
+ }
99
+ }
100
+ log(quiet, "geoip: could not determine the exit IP");
101
+ return null;
102
+ }
103
+ let _mmdbInflight = null;
104
+ async function ensureMmdb(quiet) {
105
+ const dir = geoCacheRoot();
106
+ const file = path.join(dir, "geoip-aio-all.mmdb");
107
+ if (existsSync(file)) {
108
+ const ageDays = (Date.now() - statSync(file).mtimeMs) / 86_400_000;
109
+ if (ageDays < MMDB_MAX_AGE_DAYS)
110
+ return file;
111
+ }
112
+ if (_mmdbInflight)
113
+ return _mmdbInflight;
114
+ _mmdbInflight = (async () => {
115
+ try {
116
+ mkdirSync(dir, { recursive: true });
117
+ const zip = path.join(dir, "geoip-aio-all.mmdb.zip");
118
+ log(quiet, "geoip: downloading the geoip-all-in-one database (~52 MB, first run only)");
119
+ const res = await fetch(MMDB_URL, { redirect: "follow" });
120
+ if (!res.ok || !res.body)
121
+ throw new Error(`HTTP ${res.status}`);
122
+ await pipeline(Readable.fromWeb(res.body), createWriteStream(zip));
123
+ const tmp = path.join(dir, ".extract");
124
+ rmSync(tmp, { recursive: true, force: true });
125
+ await extract(zip, { dir: tmp });
126
+ const found = findMmdb(tmp);
127
+ if (!found)
128
+ throw new Error("no .mmdb in archive");
129
+ rmSync(file, { force: true });
130
+ // move (rename across same dir)
131
+ const fs = await import("node:fs");
132
+ fs.renameSync(found, file);
133
+ rmSync(zip, { force: true });
134
+ rmSync(tmp, { recursive: true, force: true });
135
+ log(quiet, "geoip: database ready");
136
+ return file;
137
+ }
138
+ catch (e) {
139
+ log(quiet, `geoip: database fetch failed (${e.message}) — falling back to ip-api`);
140
+ return null;
141
+ }
142
+ finally {
143
+ _mmdbInflight = null;
144
+ }
145
+ })();
146
+ return _mmdbInflight;
147
+ }
148
+ function findMmdb(dir) {
149
+ const stack = [dir];
150
+ while (stack.length) {
151
+ const cur = stack.pop();
152
+ for (const e of readdirSync(cur, { withFileTypes: true })) {
153
+ const full = path.join(cur, e.name);
154
+ if (e.isDirectory())
155
+ stack.push(full);
156
+ else if (e.name.toLowerCase().endsWith(".mmdb"))
157
+ return full;
158
+ }
159
+ }
160
+ return null;
161
+ }
162
+ let _reader = null;
163
+ async function mmdbLookup(ip, quiet) {
164
+ const file = await ensureMmdb(quiet);
165
+ if (!file)
166
+ return null;
167
+ try {
168
+ if (!_reader)
169
+ _reader = await maxmind.open(file);
170
+ const rec = _reader.get(ip);
171
+ if (!rec)
172
+ return null;
173
+ const country = rec?.country?.iso_code;
174
+ const lat = rec?.location?.latitude;
175
+ const lon = rec?.location?.longitude;
176
+ const tz = rec?.location?.time_zone;
177
+ if (!tz && lat == null)
178
+ return null;
179
+ return {
180
+ ip,
181
+ country,
182
+ timezone: tz,
183
+ acceptLanguage: acceptLanguageForCountry(country),
184
+ location: lat != null && lon != null ? `${lat},${lon}` : undefined,
185
+ };
186
+ }
187
+ catch (e) {
188
+ log(quiet, `geoip: mmdb read failed (${e.message})`);
189
+ return null;
190
+ }
191
+ }
192
+ // Fallback: ip-api.com returns geo directly (through the proxy), no DB needed.
193
+ async function ipApiFallback(proxy, quiet) {
194
+ try {
195
+ const txt = await httpGetText(IPAPI_URL, proxy, 8000);
196
+ const j = JSON.parse(txt);
197
+ if (j?.status !== "success")
198
+ return null;
199
+ return {
200
+ ip: j.query,
201
+ country: j.countryCode,
202
+ timezone: j.timezone,
203
+ acceptLanguage: acceptLanguageForCountry(j.countryCode),
204
+ location: j.lat != null && j.lon != null ? `${j.lat},${j.lon}` : undefined,
205
+ };
206
+ }
207
+ catch {
208
+ return null;
209
+ }
210
+ }
211
+ /**
212
+ * Resolve geo for the egress (through `proxy` if given, else direct). Never throws — returns null
213
+ * on failure. Uses the geoip-all-in-one offline DB first, ip-api.com as a fallback.
214
+ */
215
+ export async function resolveGeo(proxy, opts = {}) {
216
+ if (isSocks(proxy)) {
217
+ log(opts.quiet, "geoip: SOCKS proxy can't be used for the geo lookup — set timezone/acceptLanguage explicitly. Skipping.");
218
+ return null;
219
+ }
220
+ const purl = proxyUrl(proxy);
221
+ const ip = await exitIp(purl, opts.quiet);
222
+ let geo = ip ? await mmdbLookup(ip, opts.quiet) : null;
223
+ if (!geo)
224
+ geo = await ipApiFallback(purl, opts.quiet);
225
+ if (geo)
226
+ log(opts.quiet, `geoip: ${geo.ip} -> ${geo.country} tz=${geo.timezone} lang=${geo.acceptLanguage}`);
227
+ return geo;
228
+ }
229
+ // country (ISO-3166 alpha-2) -> Accept-Language. Plain comma list (NO ;q= weights — Chromium's
230
+ // --accept-lang adds those). The geoip DB has no language data, so this maps the resolved country.
231
+ const COUNTRY_LANG = {
232
+ US: "en-US,en", GB: "en-GB,en", CA: "en-CA,en,fr-CA", AU: "en-AU,en", NZ: "en-NZ,en",
233
+ IE: "en-IE,en", IN: "en-IN,en,hi", ZA: "en-ZA,en", SG: "en-SG,en",
234
+ DE: "de-DE,de,en", AT: "de-AT,de,en", CH: "de-CH,de,fr,en",
235
+ FR: "fr-FR,fr,en", BE: "nl-BE,nl,fr,en", NL: "nl-NL,nl,en",
236
+ ES: "es-ES,es,en", MX: "es-MX,es,en", AR: "es-AR,es,en", CL: "es-CL,es,en",
237
+ CO: "es-CO,es,en", PT: "pt-PT,pt,en", BR: "pt-BR,pt,en",
238
+ IT: "it-IT,it,en", PL: "pl-PL,pl,en", RU: "ru-RU,ru,en", UA: "uk-UA,uk,ru,en",
239
+ SE: "sv-SE,sv,en", NO: "nb-NO,no,en", DK: "da-DK,da,en", FI: "fi-FI,fi,en",
240
+ CZ: "cs-CZ,cs,en", RO: "ro-RO,ro,en", HU: "hu-HU,hu,en", GR: "el-GR,el,en",
241
+ TR: "tr-TR,tr,en", IL: "he-IL,he,en", SA: "ar-SA,ar,en", AE: "ar-AE,ar,en",
242
+ EG: "ar-EG,ar,en", JP: "ja-JP,ja,en", KR: "ko-KR,ko,en",
243
+ CN: "zh-CN,zh,en", HK: "zh-HK,zh,en", TW: "zh-TW,zh,en",
244
+ TH: "th-TH,th,en", VN: "vi-VN,vi,en", ID: "id-ID,id,en",
245
+ MY: "ms-MY,ms,en", PH: "en-PH,en,fil",
246
+ };
247
+ export function acceptLanguageForCountry(cc) {
248
+ if (!cc)
249
+ return "en-US,en";
250
+ return COUNTRY_LANG[cc.toUpperCase()] || "en-US,en";
251
+ }
252
+ //# sourceMappingURL=geoip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geoip.js","sourceRoot":"","sources":["../src/geoip.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,12 +3,18 @@ import { type DownloadOptions } from "./download.js";
3
3
  import { type FingerprintOptions } from "./fingerprint.js";
4
4
  export type { FingerprintOptions } from "./fingerprint.js";
5
5
  export type { DownloadOptions } from "./download.js";
6
+ export { resolveGeo, type Geo } from "./geoip.js";
6
7
  export { RELEASE } from "./release.js";
8
+ /** When true (and a proxy is set), resolve the proxy's exit-IP geo and auto-fill any unset
9
+ * `timezone` + `acceptLanguage` (+ `location`) so they match the proxy region. */
10
+ interface GeoipOption {
11
+ geoip?: boolean;
12
+ }
7
13
  /** Options for {@link launch}: Playwright launch options + Clearcote fingerprint options. */
8
- export interface LaunchOptions extends PlaywrightLaunchOptions, FingerprintOptions {
14
+ export interface LaunchOptions extends PlaywrightLaunchOptions, FingerprintOptions, GeoipOption {
9
15
  }
10
16
  /** Options for {@link launchPersistentContext}. */
11
- export interface PersistentContextOptions extends PlaywrightLaunchOptions, BrowserContextOptions, FingerprintOptions {
17
+ export interface PersistentContextOptions extends PlaywrightLaunchOptions, BrowserContextOptions, FingerprintOptions, GeoipOption {
12
18
  }
13
19
  /**
14
20
  * Resolve the Clearcote chrome.exe path, downloading + verifying it if needed.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,qBAAqB,EACrB,aAAa,IAAI,uBAAuB,EACzC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAA4C,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,6FAA6F;AAC7F,MAAM,WAAW,aAAc,SAAQ,uBAAuB,EAAE,kBAAkB;CAAG;AAErF,mDAAmD;AACnD,MAAM,WAAW,wBACf,SAAQ,uBAAuB,EAC7B,qBAAqB,EACrB,kBAAkB;CAAG;AAYzB;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,eAAoB,GAC1D,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,iGAAiG;AACjG,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAED,yEAAyE;AACzE,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,cAAc,CAAC,CAUzB;;;;;;;;AAED,wBAAsF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,qBAAqB,EACrB,aAAa,IAAI,uBAAuB,EACzC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAA4C,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAIrG,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;kFACkF;AAClF,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAc,SAAQ,uBAAuB,EAAE,kBAAkB,EAAE,WAAW;CAAG;AAElG,mDAAmD;AACnD,MAAM,WAAW,wBACf,SAAQ,uBAAuB,EAC7B,qBAAqB,EACrB,kBAAkB,EAClB,WAAW;CAAG;AAqBlB;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,eAAoB,GAC1D,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,iGAAiG;AACjG,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAED,yEAAyE;AACzE,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAW1E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,cAAc,CAAC,CAWzB;;;;;;;;AAED,wBAAsF"}
package/dist/index.js CHANGED
@@ -12,8 +12,22 @@
12
12
  import { chromium } from "playwright-core";
13
13
  import { ensureBinary } from "./download.js";
14
14
  import { fingerprintArgs, splitFingerprintOptions } from "./fingerprint.js";
15
+ import { resolveGeo } from "./geoip.js";
15
16
  import { RELEASE } from "./release.js";
17
+ export { resolveGeo } from "./geoip.js";
16
18
  export { RELEASE } from "./release.js";
19
+ /** Fill unset timezone/acceptLanguage/location on `fp` from the proxy's exit-IP geo. */
20
+ async function applyGeoip(fp, proxy) {
21
+ const geo = await resolveGeo(proxy);
22
+ if (!geo)
23
+ return;
24
+ if (geo.timezone && fp.timezone == null)
25
+ fp.timezone = geo.timezone;
26
+ if (geo.acceptLanguage && fp.acceptLanguage == null)
27
+ fp.acceptLanguage = geo.acceptLanguage;
28
+ if (geo.location && fp.location == null)
29
+ fp.location = geo.location;
30
+ }
17
31
  function ensureRunnableHere(exe) {
18
32
  if (process.platform !== "win32") {
19
33
  throw new Error(`Clearcote ${RELEASE.version} ships a Windows x64 binary only — it cannot launch on '${process.platform}'.\n` +
@@ -38,8 +52,10 @@ export async function download(options = {}) {
38
52
  }
39
53
  /** Launch Clearcote and return a standard Playwright {@link Browser}. */
40
54
  export async function launch(options = {}) {
41
- const { executablePath: exeOption, args, ...rest } = options;
55
+ const { executablePath: exeOption, args, geoip, ...rest } = options;
42
56
  const { fingerprint, rest: pwOptions } = splitFingerprintOptions(rest);
57
+ if (geoip)
58
+ await applyGeoip(fingerprint, pwOptions.proxy);
43
59
  const exe = await executablePath({ executablePath: exeOption });
44
60
  ensureRunnableHere(exe);
45
61
  return chromium.launch({
@@ -53,8 +69,10 @@ export async function launch(options = {}) {
53
69
  * {@link BrowserContext} (cookies, storage, etc. persist in `userDataDir`).
54
70
  */
55
71
  export async function launchPersistentContext(userDataDir, options = {}) {
56
- const { executablePath: exeOption, args, ...rest } = options;
72
+ const { executablePath: exeOption, args, geoip, ...rest } = options;
57
73
  const { fingerprint, rest: pwOptions } = splitFingerprintOptions(rest);
74
+ if (geoip)
75
+ await applyGeoip(fingerprint, pwOptions.proxy);
58
76
  const exe = await executablePath({ executablePath: exeOption });
59
77
  ensureRunnableHere(exe);
60
78
  return chromium.launchPersistentContext(userDataDir, {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/release.js CHANGED
@@ -4,13 +4,13 @@
4
4
  // this package, the hash check guarantees you run exactly the published, signed binary.
5
5
  // Published checksums + GPG signatures live on the release page.
6
6
  export const RELEASE = {
7
- tag: "v0.1.0-pre.3",
7
+ tag: "v0.1.0-pre.4",
8
8
  version: "149.0.7827.114",
9
9
  asset: "clearcote-149.0.7827.114-windows-x64.zip",
10
- url: "https://github.com/clearcotelabs/clearcote-browser/releases/download/v0.1.0-pre.3/clearcote-149.0.7827.114-windows-x64.zip",
11
- sha256: "767cc867cbc8a622b98c3e85f5b3a37cfa587f8dff19060afe0c7783880c0aaa",
10
+ url: "https://github.com/clearcotelabs/clearcote-browser/releases/download/v0.1.0-pre.4/clearcote-149.0.7827.114-windows-x64.zip",
11
+ sha256: "40972168909e887434a3db4188d336bb7389d319a5c75967fb66ca6114c22e4c",
12
12
  exeSha256: "5743595256c89c6874804bf3315acce592fc7f1883760c8d380c010151a73b23",
13
- size: 253018691,
13
+ size: 253019015,
14
14
  os: "win32",
15
15
  };
16
16
  //# sourceMappingURL=release.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clearcote",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Playwright drop-in for the Clearcote anti-fingerprint Chromium build. launch() returns a standard Playwright Browser backed by the verified Clearcote binary, which is auto-downloaded and SHA-256 checked.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,6 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "extract-zip": "^2.0.1",
28
+ "maxmind": "^4.3.0",
28
29
  "playwright-core": "^1.49.0"
29
30
  },
30
31
  "devDependencies": {