Developer Guide
Relevant source files
The following files were used as context for generating this wiki page:This guide provides a technical overview of the GeekEZ Browser, an anti-detect browser built with Electron and Puppeteer. It is intended for developers who wish to understand, maintain, or contribute to the project. The guide covers the core architecture, profile management system, fingerprinting engine, and networking layer.
The application is a standard Electron app with a main process (main.js) handling backend logic and a renderer process (renderer.js and index.html) for the user interface. It leverages Puppeteer to control a real Chrome browser instance for each profile, Xray-core for advanced proxying, and a custom fingerprinting engine to ensure browser environment isolation and uniqueness.
1. Core Architecture
The application is built on the Electron framework, which separates the application into a Main process and one or more Renderer processes.
- Main Process (
main.js): Acts as the backend server. It manages application lifecycle, windows, native OS interactions, and all core logic. This includes launching and managing browser profiles, handling file system operations for profile data, and orchestrating the Xray-core proxy processes. - Renderer Process (
renderer.js): This is the application's user interface, running in a Chromium window (index.html). It is responsible for displaying the profile list, modals for creating/editing profiles, and managing proxy settings. It communicates with the Main process via IPC channels to perform backend operations.
The following diagram illustrates the high-level architecture of the application.
Sources: main.js, renderer.js, index.html
2. Setup and Build Process
The project relies on Node.js and several npm packages. The setup and build processes are defined in package.json and setup.js.
2.1. Initial Setup
When a developer runs npm install, the postinstall script executes setup.js. This script is responsible for downloading the necessary binary dependencies: Xray-core and a specific version of Chromium for Puppeteer.
The setup process is as follows:
- Network Check: The script checks for global internet access by trying to connect to
google.com. - Select Download Mirror: If the check fails, it assumes a CN (China) environment and uses a GitHub proxy (
gh-proxy.com) for Xray-core and a mirror for Chromium (npmmirror.com). - Download & Extract Xray-core: It downloads the correct Xray-core binary for the user's OS and architecture, extracts it to
resources/bin, and sets executable permissions on non-Windows systems. - Download & Unpack Chromium: It uses the
@puppeteer/browserspackage to download and unpack a specific build of Chrome (129.0.6668.58) into theresources/puppeteerdirectory.
This flow is visualized below.
Sources: setup.js:10-176, package.json:8-9
2.2. Build Scripts
The package.json file contains scripts to build the application for different platforms using electron-builder.
| Script | Description |
|---|---|
npm start | Runs the application in development mode using electron .. |
npm run build:win | Builds a Windows (x64) installer (.exe). |
npm run build:mac | Builds a macOS (arm64 & x64) installer (.dmg). |
npm run build:linux | Builds a Linux installer (.AppImage). |
Sources: package.json:7-12
3. Profile Management
Browser profiles are the core entity in GeekEZ. Each profile represents an isolated browser environment with a unique fingerprint, storage, and network configuration.
3.1. Data Storage
Profile data and application settings are stored as JSON files in the user's application data directory (app.getPath('userData')).
BrowserProfiles/profiles.json: An array of profile objects.BrowserProfiles/settings.json: Global settings, including pre-proxy configurations, subscriptions, and UI preferences.BrowserProfiles/<profile_id>/: A directory for each profile containing its persistent browser data (browser_data) and temporary configuration files (config.json).
Sources: main.js:19-24
3.2. Profile Data Structure
A profile object contains metadata, proxy information, and the generated fingerprint.
This diagram shows the main fields of a profile object as stored in profiles.json.
Sources: main.js:283-285
3.3. Profile CRUD Operations
All profile management is handled by the main process via IPC channels. The renderer process sends requests to create, read, update, or delete profiles.
This sequence diagram shows how a new profile is created.
Sources: renderer.js:636-651, main.js:281-286
4. Fingerprint Spoofing
The core anti-detect functionality comes from the fingerprinting engine, defined in fingerprint.js. It generates a unique fingerprint for each profile and creates a JavaScript payload to inject into every web page.
4.1. Fingerprint Generation
The generateFingerprint() function creates a fingerprint object with randomized and spoofed browser properties.
Key spoofed attributes include:
| Property | Spoofing Method |
|---|---|
userAgent | Set to a standard Chrome UA matching the host OS. |
platform | Set to Win32, MacIntel, or Linux x86_64 based on host OS. |
screen / window | Randomly selected from a predefined list of common resolutions. |
webgl | Hardcoded to a common NVIDIA GPU value. |
hardwareConcurrency | Randomized between 4, 8, 12, and 16. |
deviceMemory | Randomized between 4, 8, and 16 GB. |
canvasNoise | Small random RGBa noise values for canvas fingerprinting. |
audioNoise | A small random value for AudioContext fingerprinting. |
timezone | Set to a specific value, defaults to America/Los_Angeles. Can be customized per profile. |
Sources: fingerprint.js:9-98, CHANGELOG_v1.2.3.md
4.2. Fingerprint Injection
For each profile, a dynamic Chrome extension (GeekEZ Guard) is generated. This extension's content script (content.js) contains the JavaScript payload from getInjectScript(fingerprint). This script runs at document_start in the MAIN world, ensuring the spoofed values are applied before any page scripts can execute.
The injection script overrides native browser APIs to return the spoofed values from the profile's fingerprint.
// Example from fingerprint.js: Hiding the WebDriver flag
if (navigator.webdriver) {
Object.defineProperty(navigator, 'webdriver', { get: () => false });
}
// Example: Applying Canvas noise
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
CanvasRenderingContext2D.prototype.getImageData = function(x, y, w, h) {
const imageData = originalGetImageData.apply(this, arguments);
if (fp.noiseSeed) {
// ... noise application logic ...
}
return imageData;
};
Sources: fingerprint.js:102-200, main.js:101-114
The process of generating and applying the fingerprint is as follows:
Sources: main.js:101-114, 282, 421-424, fingerprint.js
5. Profile Launch and Networking
Launching a profile involves orchestrating an Xray-core process and a Puppeteer-controlled Chrome instance.
5.1. Launch Sequence
The launch-profile IPC handler in main.js manages this entire process.
Sources: main.js:321-508
5.2. Proxy and Network Configuration
GeekEZ Browser uses Xray-core to handle all proxying.
- Profile Proxy: Each profile has a primary proxy link (e.g.,
vmess://,ss://). - Pre-Proxy (Chain Proxy): The application supports a global chain proxy. When enabled, traffic flows from
Chrome -> Profile Proxy (via Xray) -> Pre-Proxy (via Xray) -> Destination. This is configured in the "Proxy Chain" manager. - Xray Configuration: The
generateXrayConfigfunction (fromutils.js, referenced inmain.js) creates a JSON configuration for Xray on the fly. This config sets up an inbound SOCKS5 listener on a free local port and routes traffic through the specified outbound proxy (and pre-proxy, if active). - Puppeteer Integration: The Chrome instance is launched with the
--proxy-server=socks5://127.0.0.1:<localPort>argument, forcing all browser traffic through the local Xray instance. - WebRTC Leak Protection: The
disable_non_proxied_udppolicy is enforced to prevent WebRTC from leaking the real IP address.
Sources: main.js:370-394, 432, 436, README.md
6. IPC Communication API
Communication between the renderer and main processes is handled via Electron's IPC mechanism. Below is a table of key IPC channels defined in main.js.
| Channel | Type | Parameters | Description |
|---|---|---|---|
get-app-info | handle | - | Returns application name and version. |
fetch-url | handle | url | Fetches the content of a given URL (used for subscriptions). |
test-proxy-latency | handle | proxyStr | Spawns a temporary Xray instance to test the latency of a proxy link. |
get-profiles | handle | - | Reads and returns all profiles from profiles.json. |
save-profile | handle | profileData | Creates a new profile with a generated fingerprint and saves it. |
update-profile | handle | updatedProfile | Updates an existing profile object in profiles.json. |
delete-profile | handle | id | Deletes a profile and moves its data directory to a trash folder. |
get-settings | handle | - | Reads and returns global settings from settings.json. |
save-settings | handle | settings | Writes the global settings object to settings.json. |
launch-profile | handle | profileId | Initiates the full profile launch sequence. |
get-running-ids | handle | - | Returns an array of IDs for currently running profiles. |
select-extension-folder | handle | - | Opens a native dialog to select a folder for a custom extension. |
add-user-extension | handle | extPath | Adds a custom extension path to settings.json. |
profile-status | send | {id, status} | Sent from main to renderer to update the running status of a profile. |
Sources: main.js:117-320, renderer.js