π Launch & Connect β Start the Browser β
Launch the Nothing Browser binary locally or connect to a remote Piggy server. Control browser mode, binary selection, and tab pooling.
β οΈ Version Requirement: Binary v0.1.14+ | Library v0.0.20+
Overview β
Piggy supports two connection modes:
| Mode | Transport | Use Case |
|---|---|---|
| Local launch | Unix socket / Windows pipe | Same-machine scraping, development |
| Remote connect | HTTP (port 2005) | VPS deployment, team access |
Local Launch β
piggy.launch(opts?) β
Spawns the Nothing Browser binary and connects over a local socket.
import piggy from "nothing-browser";
// Default: headless, tab mode
await piggy.launch();
// With options
await piggy.launch({
mode: "tab", // "tab" | "process"
binary: "headless" // "headless" | "headful" | "/custom/path"
});Launch Options β
| Option | Type | Default | Description |
|---|---|---|---|
mode | "tab" | "process" | "tab" | Tab mode: single browser, multiple tabs. Process mode: separate browser per site |
binary | "headless" | "headful" | string | "headless" | Binary to use. Custom string = path to binary |
Linux / macOS (Simple) β
// Just works β binary in project root
await piggy.launch({ binary: "headless" });Windows (Custom Path Required) β
Windows binaries require .dll files. Keep them together in a folder:
C:\my-scraper\
βββ brow\
β βββ nothing-browser-headless.exe
βββ index.ts// Windows β full path to .exe
await piggy.launch({
binary: "brow/nothing-browser-headless.exe"
});Custom Binary Path (Any OS) β
// Absolute path
await piggy.launch({
binary: "/opt/browsers/nothing-browser-headless"
});
// Relative path
await piggy.launch({
binary: "./binaries/nothing-browser-headless"
});
// Windows absolute
await piggy.launch({
binary: "C:\\browsers\\nothing-browser-headless.exe"
});Remote Connect β
piggy.connect({ host, key }) β
Connects to a running Piggy server over HTTP (port 2005). The server must be started separately with ./nothing-browser-headless in HTTP mode.
await piggy.connect({
host: "http://localhost:2005",
key: "peaseernestbd7436aecf7041a39532a03308b8ee3350495f3cdb534b8294f9d"
});First-Time Server Setup (VPS) β
# Upload binary to VPS, SSH in, run:
./nothing-browser-headless
# Choose HTTP mode, enter session name
Mode? (socket/http): http
Session name: my-server
# Copy the generated key (shown once)
Key: peaseernestbd7436aecf7041a39532a03308b8ee3350495f3cdb534b8294f9d
# Run in background
nohup ./nothing-browser-headless > piggy.log 2>&1 &Connect from Code β
await piggy.connect({
host: "http://your-vps-ip:2005",
key: process.env.PIGGY_KEY // Store in env variable
});Register a Site β
piggy.register(name, url, opts?) β
Registers a site and attaches a SiteObject as piggy[name].
await piggy.register("amazon", "https://www.amazon.com");
// Now use it
await piggy.amazon.navigate();
const title = await piggy.amazon.title();Register Options β
| Option | Type | Default | Description |
|---|---|---|---|
binary | string | Same as launch | Override binary for this site |
pool | number | 1 | Number of tabs for concurrent requests |
With Tab Pooling β
// 4 concurrent requests to same site
await piggy.register("amazon", "https://www.amazon.com", { pool: 4 });With Custom Binary Per Site β
await piggy.launch({ binary: "headless" });
// This one runs headful for debugging
await piggy.register("debug", "https://example.com", {
binary: "headful"
});Close β
piggy.close(opts?) β
Shuts down the browser and cleans up resources.
// Graceful close (waits for active operations)
await piggy.close();
// Force kill immediately
await piggy.close({ force: true });Keeping Sites Alive β
Use noclose() to prevent a site from closing when piggy.close() is called.
await piggy.register("api", "https://api.example.com");
piggy.api.noclose(); // Won't close on piggy.close()
await piggy.close(); // api stays alive, others closeDetect Binary β
piggy.detect(binary) β
Checks if a binary exists without launching.
const headlessPath = piggy.detect("headless");
const headfulPath = piggy.detect("headful");
const customPath = piggy.detect("./brow/nothing-browser-headless.exe");
console.log("Headless found at:", headlessPath);
console.log("Headful found at:", headfulPath);Returns string with full path, or null if not found.
Human Mode β
piggy.actHuman(enable) β
Enables human-like behavior (random delays, smooth scrolling, natural typing) for all interactions.
// Enable globally
piggy.actHuman(true);
await piggy.amazon.click("button"); // Has random delay
await piggy.amazon.type("#search", "laptop"); // Variable typing speed
// Disable
piggy.actHuman(false);Mode β
piggy.mode(mode) β
Sets the default tab mode for subsequent register() calls.
// Each site gets its own browser process
piggy.mode("process");
await piggy.register("site1", "https://example.com");
await piggy.register("site2", "https://example.org");
// Back to tab mode
piggy.mode("tab");| Mode | Description |
|---|---|
"tab" | Single browser, multiple tabs (default) |
"process" | Separate browser per site |
Complete Examples β
Example 1: Local Development β
import piggy from "nothing-browser";
// Launch browser
await piggy.launch({ mode: "tab", binary: "headless" });
// Enable human mode for realistic behavior
piggy.actHuman(true);
// Register sites
await piggy.register("amazon", "https://www.amazon.com");
await piggy.register("ebay", "https://www.ebay.com");
// Navigate
await piggy.amazon.navigate();
await piggy.amazon.wait.selector({ selector: "[data-asin]" });
const products = await piggy.amazon.provide.textAll({ selector: ".title" });
console.log(products);
await piggy.close();Example 2: Remote VPS Deployment β
import piggy from "nothing-browser";
// Connect to remote server
await piggy.connect({
host: process.env.PIGGY_HOST,
key: process.env.PIGGY_KEY
});
// Register site
await piggy.register("amazon", "https://www.amazon.com");
// Scrape
await piggy.amazon.navigate();
const title = await piggy.amazon.title();
console.log(title);
// Don't close β server stays running
// await piggy.close(); // Only call when shutting downExample 3: Tab Pooling for High Concurrency β
import piggy from "nothing-browser";
await piggy.launch({ mode: "tab", binary: "headless" });
// Pool of 4 tabs for concurrent API requests
await piggy.register("amazon", "https://www.amazon.com", { pool: 4 });
// API server with 4 concurrent scrapers
await piggy.amazon.api("/search", async (_params, query) => {
const term = query.q ?? "laptop";
await piggy.amazon.navigate(`https://amazon.com/s?k=${term}`);
// ... scraping logic
return { term, products };
});
await piggy.serve(3000);Example 4: Multiple Processes (Isolation) β
import piggy from "nothing-browser";
// Each site gets its own browser process
await piggy.launch({ mode: "process" });
await piggy.register("site1", "https://site1.com");
await piggy.register("site2", "https://site2.com");
// They run completely independently
await Promise.all([
piggy.site1.navigate(),
piggy.site2.navigate()
]);
const [title1, title2] = await Promise.all([
piggy.site1.title(),
piggy.site2.title()
]);
console.log({ title1, title2 });
await piggy.close();Error Handling β
try {
await piggy.launch({ binary: "headless" });
} catch (error) {
console.error("Failed to launch:", error.message);
// Check: binary exists? permissions? dependencies?
}
try {
await piggy.connect({ host: "http://localhost:2005", key: "wrong-key" });
} catch (error) {
console.error("Connection failed:", error.message);
// Invalid key or server not running
}
try {
await piggy.register("site", "https://example.com");
} catch (error) {
console.error("Registration failed:", error.message);
// Call launch() or connect() first
}Binary Detection Path Order β
| Input | Search Locations |
|---|---|
"headless" | 1. ./nothing-browser-headless2. ./bin/nothing-browser-headless3. System PATH |
"headful" | Same as above, with -headful suffix |
| Custom string | Exact path (no search) |
API Reference β
Global Methods β
| Method | Parameters | Returns | Description |
|---|---|---|---|
launch(opts?) | { mode?, binary? } | Promise<piggy> | Start local browser |
connect(opts) | { host, key } | Promise<piggy> | Connect to remote server |
register(name, url, opts?) | name, url, { binary?, pool? } | Promise<piggy> | Register a site |
close(opts?) | { force? } | Promise<void> | Shutdown |
actHuman(enable) | enable: boolean | piggy | Enable human mode |
mode(mode) | mode: "tab" | "process" | piggy | Set tab mode |
detect(binary) | binary: string | string | null | Check binary exists |
Site Methods β
| Method | Parameters | Returns | Description |
|---|---|---|---|
noclose() | β | SiteObject | Prevent closing on piggy.close() |
poolStats() | β | { idle, busy, queued, total } | Pool statistics (if pool > 1) |
close() | β | Promise<void> | Close this site only |
Type Definitions β
interface LaunchOptions {
mode?: "tab" | "process";
binary?: "headless" | "headful" | string;
}
interface ConnectOptions {
host: string;
key: string;
}
interface RegisterOptions {
binary?: "headless" | "headful" | string;
pool?: number;
}
interface PoolStats {
idle: number;
busy: number;
queued: number;
total: number;
}Next Steps β
- Navigation β Navigate, reload, back/forward
- Interactions β Click, type, hover
- Find API β Query DOM elements
Nothing Ecosystem Β· Ernest Tech House Β· Kenya Β· 2026