@hieutran094/camoufox-js 0.6.2

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.
@@ -0,0 +1,51 @@
1
+ navigator: >-
2
+ Manually setting navigator properties is not recommended.
3
+ Device information is automatically generated within Camoufox
4
+ based on the provided `os`.
5
+
6
+ locale: >-
7
+ Use the `locale` parameter in Camoufox instead of setting the config manually.
8
+
9
+ geolocation: >-
10
+ Please use the `geoip` parameter in Camoufox instead of setting your geolocation manually.
11
+ This can lead to detection if your target geolocation does not match your IP.
12
+ Pass `geoip=True` or a target IP (ex: geoip='123.45.67.89') to let Camoufox populate this data for you.
13
+
14
+ header-ua: >-
15
+ Do not set the header.User-Agent manually. Camoufox will generate a User-Agent for you.
16
+
17
+ viewport: >-
18
+ Manually setting screen & window properties is not recommended.
19
+ Screen dimensions are randomly generated within Camoufox
20
+ based on the provided screen constraints. See here:
21
+ https://github.com/daijro/camoufox/tree/main/pythonlib#browserforge-integration.
22
+
23
+ custom_fingerprint: >-
24
+ Passing your own fingerprint is not recommended.
25
+ BrowserForge fingerprints are automatically generated within Camoufox
26
+ based on the provided `os` and `screen` constraints.
27
+
28
+ proxy_without_geoip: >-
29
+ When using a proxy, it is heavily recommended that you pass `geoip=True`.
30
+
31
+ ff_version: >-
32
+ Spoofing the Firefox version will likely lead to detection.
33
+ If rotating the Firefox version is absolutely necessary, it would be more advisable to
34
+ rotate between older versions of Camoufox instead.
35
+
36
+ no_region: >-
37
+ Because you did not pass in a locale region, Camoufox will generate one for you.
38
+ This can cause suspicion if your IP does not match your locale region.
39
+
40
+ block_webgl: >-
41
+ Disabling WebGL is not recommended. Many WAFs will check if WebGL is enabled.
42
+
43
+ block_images: >-
44
+ Blocking image requests has been reported to cause detection issues on major WAFs.
45
+
46
+ custom_fonts_only: >-
47
+ Disabling OS-specific fonts while spoofing your OS will make your browser fingerprint inconsistent.
48
+ WAFs can detect this mismatch between your claimed OS and available system fonts.
49
+
50
+ disable_coop: >-
51
+ Disabling Cross-Origin-Opener-Policy (COOP) handling can potentially be detected by sophisticated WAFs.
Binary file
@@ -0,0 +1,76 @@
1
+ export declare class UnsupportedVersion extends Error {
2
+ constructor(message?: string);
3
+ }
4
+ export declare class MissingRelease extends Error {
5
+ constructor(message?: string);
6
+ }
7
+ export declare class UnsupportedArchitecture extends Error {
8
+ constructor(message?: string);
9
+ }
10
+ export declare class UnsupportedOS extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ export declare class UnknownProperty extends Error {
14
+ constructor(message?: string);
15
+ }
16
+ export declare class InvalidPropertyType extends Error {
17
+ constructor(message?: string);
18
+ }
19
+ export declare class InvalidAddonPath extends Error {
20
+ constructor(message?: string);
21
+ }
22
+ export declare class InvalidDebugPort extends Error {
23
+ constructor(message?: string);
24
+ }
25
+ export declare class MissingDebugPort extends Error {
26
+ constructor(message?: string);
27
+ }
28
+ export declare class LocaleError extends Error {
29
+ constructor(message: string);
30
+ }
31
+ export declare class InvalidIP extends Error {
32
+ constructor(message?: string);
33
+ }
34
+ export declare class InvalidProxy extends Error {
35
+ constructor(message?: string);
36
+ }
37
+ export declare class UnknownIPLocation extends LocaleError {
38
+ constructor(message?: string);
39
+ }
40
+ export declare class InvalidLocale extends LocaleError {
41
+ constructor(message?: string);
42
+ static invalidInput(locale: string): InvalidLocale;
43
+ }
44
+ export declare class UnknownTerritory extends InvalidLocale {
45
+ constructor(message?: string);
46
+ }
47
+ export declare class UnknownLanguage extends InvalidLocale {
48
+ constructor(message?: string);
49
+ }
50
+ export declare class NotInstalledGeoIPExtra extends Error {
51
+ constructor(message?: string);
52
+ }
53
+ export declare class NonFirefoxFingerprint extends Error {
54
+ constructor(message?: string);
55
+ }
56
+ export declare class InvalidOS extends Error {
57
+ constructor(message?: string);
58
+ }
59
+ export declare class VirtualDisplayError extends Error {
60
+ constructor(message?: string);
61
+ }
62
+ export declare class CannotFindXvfb extends VirtualDisplayError {
63
+ constructor(message?: string);
64
+ }
65
+ export declare class CannotExecuteXvfb extends VirtualDisplayError {
66
+ constructor(message?: string);
67
+ }
68
+ export declare class VirtualDisplayNotSupported extends VirtualDisplayError {
69
+ constructor(message?: string);
70
+ }
71
+ export declare class CamoufoxNotInstalled extends Error {
72
+ constructor(message?: string);
73
+ }
74
+ export declare class FileNotFoundError extends Error {
75
+ constructor(message?: string);
76
+ }
@@ -0,0 +1,153 @@
1
+ export class UnsupportedVersion extends Error {
2
+ constructor(message) {
3
+ super(message ?? "The Camoufox executable is outdated.");
4
+ this.name = "UnsupportedVersion";
5
+ }
6
+ }
7
+ export class MissingRelease extends Error {
8
+ constructor(message) {
9
+ super(message ?? "A required GitHub release asset is missing.");
10
+ this.name = "MissingRelease";
11
+ }
12
+ }
13
+ export class UnsupportedArchitecture extends Error {
14
+ constructor(message) {
15
+ super(message ?? "The architecture is not supported.");
16
+ this.name = "UnsupportedArchitecture";
17
+ }
18
+ }
19
+ export class UnsupportedOS extends Error {
20
+ constructor(message) {
21
+ super(message ?? "The OS is not supported.");
22
+ this.name = "UnsupportedOS";
23
+ }
24
+ }
25
+ export class UnknownProperty extends Error {
26
+ constructor(message) {
27
+ super(message ?? "The property is unknown.");
28
+ this.name = "UnknownProperty";
29
+ }
30
+ }
31
+ export class InvalidPropertyType extends Error {
32
+ constructor(message) {
33
+ super(message ?? "The property type is invalid.");
34
+ this.name = "InvalidPropertyType";
35
+ }
36
+ }
37
+ export class InvalidAddonPath extends Error {
38
+ constructor(message) {
39
+ super(message ?? "The addon path is invalid.");
40
+ this.name = "InvalidAddonPath";
41
+ }
42
+ }
43
+ export class InvalidDebugPort extends Error {
44
+ constructor(message) {
45
+ super(message ?? "The debug port is invalid.");
46
+ this.name = "InvalidDebugPort";
47
+ }
48
+ }
49
+ export class MissingDebugPort extends Error {
50
+ constructor(message) {
51
+ super(message ?? "The debug port is missing.");
52
+ this.name = "MissingDebugPort";
53
+ }
54
+ }
55
+ export class LocaleError extends Error {
56
+ constructor(message) {
57
+ super(message ?? "The locale is invalid.");
58
+ this.name = "LocaleError";
59
+ }
60
+ }
61
+ export class InvalidIP extends Error {
62
+ constructor(message) {
63
+ super(message ?? "An IP address is invalid.");
64
+ this.name = "InvalidIP";
65
+ }
66
+ }
67
+ export class InvalidProxy extends Error {
68
+ constructor(message) {
69
+ super(message ?? "A proxy is invalid.");
70
+ this.name = "InvalidProxy";
71
+ }
72
+ }
73
+ export class UnknownIPLocation extends LocaleError {
74
+ constructor(message) {
75
+ super(message ?? "The location of an IP is unknown.");
76
+ this.name = "UnknownIPLocation";
77
+ }
78
+ }
79
+ export class InvalidLocale extends LocaleError {
80
+ constructor(message) {
81
+ super(message ?? "The locale input is invalid.");
82
+ this.name = "InvalidLocale";
83
+ }
84
+ static invalidInput(locale) {
85
+ return new InvalidLocale(`Invalid locale: '${locale}'. Must be either a region, language, language-region, or language-script-region.`);
86
+ }
87
+ }
88
+ export class UnknownTerritory extends InvalidLocale {
89
+ constructor(message) {
90
+ super(message ?? "The territory is unknown.");
91
+ this.name = "UnknownTerritory";
92
+ }
93
+ }
94
+ export class UnknownLanguage extends InvalidLocale {
95
+ constructor(message) {
96
+ super(message ?? "The language is unknown.");
97
+ this.name = "UnknownLanguage";
98
+ }
99
+ }
100
+ export class NotInstalledGeoIPExtra extends Error {
101
+ constructor(message) {
102
+ super(message ?? "The geoip2 module is not installed.");
103
+ this.name = "NotInstalledGeoIPExtra";
104
+ }
105
+ }
106
+ export class NonFirefoxFingerprint extends Error {
107
+ constructor(message) {
108
+ super(message ?? "A passed Browserforge fingerprint is invalid.");
109
+ this.name = "NonFirefoxFingerprint";
110
+ }
111
+ }
112
+ export class InvalidOS extends Error {
113
+ constructor(message) {
114
+ super(message ?? "The target OS is invalid.");
115
+ this.name = "InvalidOS";
116
+ }
117
+ }
118
+ export class VirtualDisplayError extends Error {
119
+ constructor(message) {
120
+ super(message ?? "There is an error with the virtual display.");
121
+ this.name = "VirtualDisplayError";
122
+ }
123
+ }
124
+ export class CannotFindXvfb extends VirtualDisplayError {
125
+ constructor(message) {
126
+ super(message ?? "Xvfb cannot be found.");
127
+ this.name = "CannotFindXvfb";
128
+ }
129
+ }
130
+ export class CannotExecuteXvfb extends VirtualDisplayError {
131
+ constructor(message) {
132
+ super(message ?? "Xvfb cannot be executed.");
133
+ this.name = "CannotExecuteXvfb";
134
+ }
135
+ }
136
+ export class VirtualDisplayNotSupported extends VirtualDisplayError {
137
+ constructor(message) {
138
+ super(message ?? "The user tried to use a virtual display on a non-Linux OS.");
139
+ this.name = "VirtualDisplayNotSupported";
140
+ }
141
+ }
142
+ export class CamoufoxNotInstalled extends Error {
143
+ constructor(message) {
144
+ super(message ?? "Camoufox is not installed.");
145
+ this.name = "CamoufoxNotInstalled";
146
+ }
147
+ }
148
+ export class FileNotFoundError extends Error {
149
+ constructor(message) {
150
+ super(message ?? "File couldn't be found.");
151
+ this.name = "FileNotFoundError";
152
+ }
153
+ }
@@ -0,0 +1,4 @@
1
+ import { Fingerprint, FingerprintGeneratorOptions } from 'fingerprint-generator';
2
+ export declare const SUPPORTED_OS: readonly ["linux", "macos", "windows"];
3
+ export declare function fromBrowserforge(fingerprint: Fingerprint, ffVersion?: string): Record<string, any>;
4
+ export declare function generateFingerprint(window?: [number, number], config?: Partial<FingerprintGeneratorOptions>): Fingerprint;
@@ -0,0 +1,84 @@
1
+ import { join } from 'node:path';
2
+ import { loadYaml } from './pkgman.js';
3
+ import { FingerprintGenerator } from 'fingerprint-generator';
4
+ export const SUPPORTED_OS = ['linux', 'macos', 'windows'];
5
+ const BROWSERFORGE_DATA = loadYaml(join(import.meta.dirname, 'data-files', 'browserforge.yml'));
6
+ const FP_GENERATOR = new FingerprintGenerator({
7
+ browsers: ['firefox'],
8
+ operatingSystems: SUPPORTED_OS,
9
+ });
10
+ function randrange(min, max) {
11
+ return Math.floor(Math.random() * (max - min + 1)) + min;
12
+ }
13
+ function _castToProperties(camoufoxData, castEnum, bfDict, ffVersion) {
14
+ for (let [key, data] of Object.entries(bfDict)) {
15
+ if (!data)
16
+ continue;
17
+ const typeKey = castEnum[key];
18
+ if (!typeKey)
19
+ continue;
20
+ if (typeof data === 'object' && !Array.isArray(data)) {
21
+ _castToProperties(camoufoxData, typeKey, data, ffVersion);
22
+ continue;
23
+ }
24
+ if (typeKey.startsWith("screen.") && typeof data === 'number' && data < 0) {
25
+ data = 0;
26
+ }
27
+ if (ffVersion && typeof data === 'string') {
28
+ data = data.replace(/(?<!\d)(1[0-9]{2})(\.0)(?!\d)/, `${ffVersion}$2`);
29
+ }
30
+ camoufoxData[typeKey] = data;
31
+ }
32
+ }
33
+ function handleScreenXY(camoufoxData, fpScreen) {
34
+ if ('window.screenY' in camoufoxData)
35
+ return;
36
+ let screenX = fpScreen.screenX;
37
+ if (!screenX) {
38
+ camoufoxData['window.screenX'] = 0;
39
+ camoufoxData['window.screenY'] = 0;
40
+ return;
41
+ }
42
+ if (screenX >= -50 && screenX <= 50) {
43
+ camoufoxData['window.screenY'] = screenX;
44
+ return;
45
+ }
46
+ let screenY = fpScreen.availHeight - fpScreen.outerHeight;
47
+ if (screenY === 0) {
48
+ camoufoxData['window.screenY'] = 0;
49
+ }
50
+ else if (screenY > 0) {
51
+ camoufoxData['window.screenY'] = randrange(0, screenY);
52
+ }
53
+ else {
54
+ camoufoxData['window.screenY'] = randrange(screenY, 0);
55
+ }
56
+ }
57
+ export function fromBrowserforge(fingerprint, ffVersion) {
58
+ const camoufoxData = {};
59
+ _castToProperties(camoufoxData, BROWSERFORGE_DATA, { ...fingerprint }, ffVersion);
60
+ handleScreenXY(camoufoxData, fingerprint.screen);
61
+ return camoufoxData;
62
+ }
63
+ function handleWindowSize(fp, outerWidth, outerHeight) {
64
+ const sc = { ...fp.screen, screenY: undefined };
65
+ sc.screenX += Math.floor((sc.width - outerWidth) / 2);
66
+ sc.screenY = Math.floor((sc.height - outerHeight) / 2);
67
+ if (sc.innerWidth) {
68
+ sc.innerWidth = Math.max(outerWidth - sc.outerWidth + sc.innerWidth, 0);
69
+ }
70
+ if (sc.innerHeight) {
71
+ sc.innerHeight = Math.max(outerHeight - sc.outerHeight + sc.innerHeight, 0);
72
+ }
73
+ sc.outerWidth = outerWidth;
74
+ sc.outerHeight = outerHeight;
75
+ fp.screen = sc;
76
+ }
77
+ export function generateFingerprint(window, config) {
78
+ if (window) {
79
+ const { fingerprint } = FP_GENERATOR.getFingerprint(config);
80
+ handleWindowSize(fingerprint, window[0], window[1]);
81
+ return fingerprint;
82
+ }
83
+ return FP_GENERATOR.getFingerprint(config).fingerprint;
84
+ }
@@ -0,0 +1,3 @@
1
+ export { Camoufox, NewBrowser } from './sync_api.js';
2
+ export { type LaunchOptions, launchOptions } from './utils.js';
3
+ export { launchServer } from './server.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { Camoufox, NewBrowser } from './sync_api.js';
2
+ export { launchOptions } from './utils.js';
3
+ export { launchServer } from './server.js';
package/dist/ip.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ export declare class InvalidIP extends Error {
2
+ }
3
+ export declare class InvalidProxy extends Error {
4
+ }
5
+ export interface Proxy {
6
+ server: string;
7
+ username?: string;
8
+ password?: string;
9
+ bypass?: string;
10
+ }
11
+ export declare class ProxyHelper {
12
+ static parseServer(server: string): {
13
+ schema: string;
14
+ url: string;
15
+ port?: string;
16
+ };
17
+ static asString(proxy: Proxy): string;
18
+ static asAxiosProxy(proxyString: string): {
19
+ [key: string]: string;
20
+ };
21
+ }
22
+ export declare function validIPv4(ip: string | false): boolean;
23
+ export declare function validIPv6(ip: string | false): boolean;
24
+ export declare function validateIP(ip: string): void;
25
+ export declare function publicIP(proxy?: string): Promise<string>;
package/dist/ip.js ADDED
@@ -0,0 +1,90 @@
1
+ import { Impit } from 'impit';
2
+ export class InvalidIP extends Error {
3
+ }
4
+ export class InvalidProxy extends Error {
5
+ }
6
+ export class ProxyHelper {
7
+ static parseServer(server) {
8
+ const proxyMatch = server.match(/^(?:(\w+):\/\/)?(.*?)(?::(\d+))?$/);
9
+ if (!proxyMatch) {
10
+ throw new InvalidProxy(`Invalid proxy server: ${server}`);
11
+ }
12
+ return {
13
+ schema: proxyMatch[1] || 'http',
14
+ url: proxyMatch[2],
15
+ port: proxyMatch[3]
16
+ };
17
+ }
18
+ static asString(proxy) {
19
+ const { schema, url, port } = this.parseServer(proxy.server);
20
+ let result = `${schema}://`;
21
+ if (proxy.username) {
22
+ result += proxy.username;
23
+ if (proxy.password) {
24
+ result += `:${proxy.password}`;
25
+ }
26
+ result += '@';
27
+ }
28
+ result += url;
29
+ if (port) {
30
+ result += `:${port}`;
31
+ }
32
+ return result;
33
+ }
34
+ static asAxiosProxy(proxyString) {
35
+ return {
36
+ http: proxyString,
37
+ https: proxyString,
38
+ };
39
+ }
40
+ }
41
+ export function validIPv4(ip) {
42
+ if (!ip) {
43
+ return false;
44
+ }
45
+ return /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(ip);
46
+ }
47
+ export function validIPv6(ip) {
48
+ if (!ip) {
49
+ return false;
50
+ }
51
+ return /^(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})$/.test(ip);
52
+ }
53
+ export function validateIP(ip) {
54
+ if (!validIPv4(ip) && !validIPv6(ip)) {
55
+ throw new InvalidIP(`Invalid IP address: ${ip}`);
56
+ }
57
+ }
58
+ export async function publicIP(proxy) {
59
+ const URLS = [
60
+ "https://api.ipify.org",
61
+ "https://checkip.amazonaws.com",
62
+ "https://ipinfo.io/ip",
63
+ "https://icanhazip.com",
64
+ "https://ifconfig.co/ip",
65
+ "https://ipecho.net/plain",
66
+ ];
67
+ const errors = [];
68
+ for (const url of URLS) {
69
+ try {
70
+ const impit = new Impit({
71
+ proxyUrl: proxy,
72
+ timeout: 5000,
73
+ });
74
+ const response = await impit.fetch(url);
75
+ if (!response.ok) {
76
+ continue;
77
+ }
78
+ const ip = (await response.text()).trim();
79
+ validateIP(ip);
80
+ return ip;
81
+ }
82
+ catch (error) {
83
+ errors.push(error);
84
+ if (process.env.CAMOUFOX_DEBUG) {
85
+ console.warn(new InvalidProxy(`camoufox-js(warn): Failed to fetch public proxy IP from ${url}, retrying with another URL...`, { cause: error }));
86
+ }
87
+ }
88
+ }
89
+ throw new InvalidIP("Failed to get a public proxy IP address from any API endpoint.", { cause: errors });
90
+ }
@@ -0,0 +1,26 @@
1
+ export declare const ALLOW_GEOIP = true;
2
+ declare class Locale {
3
+ language: string;
4
+ region?: string | undefined;
5
+ script?: string | undefined;
6
+ constructor(language: string, region?: string | undefined, script?: string | undefined);
7
+ asString(): string;
8
+ asConfig(): Record<string, string>;
9
+ }
10
+ declare class Geolocation {
11
+ locale: Locale;
12
+ longitude: number;
13
+ latitude: number;
14
+ timezone: string;
15
+ accuracy?: number | undefined;
16
+ constructor(locale: Locale, longitude: number, latitude: number, timezone: string, accuracy?: number | undefined);
17
+ asConfig(): Record<string, any>;
18
+ }
19
+ export declare function normalizeLocale(locale: string): Locale;
20
+ export declare function handleLocale(locale: string, ignoreRegion?: boolean): Locale;
21
+ export declare function handleLocales(locales: string | string[], config: Record<string, any>): void;
22
+ export declare function geoipAllowed(): void;
23
+ export declare function downloadMMDB(): Promise<void>;
24
+ export declare function removeMMDB(): void;
25
+ export declare function getGeolocation(ip: string): Promise<Geolocation>;
26
+ export {};