πͺ Cookies Hot Reload β Edit Cookies While Browser Runs β
Edit cookies.json while Piggy is running β changes apply immediately without restart. Perfect for session rotation, testing different auth states, or debugging cookie-related issues.
Overview β
Piggy saves cookies to cookies.json in your working directory. Unlike traditional browsers that require restart to load new cookies, Piggy supports hot reload β edit the file and call sessionReload() to apply changes instantly.
| Feature | Traditional Browser | Piggy |
|---|---|---|
| Cookies persist across restarts | β Yes | β Yes |
| Edit cookies while browser runs | β No (need restart) | β Yes (hot reload) |
| Drop new cookie file | β No | β Yes |
| Programmatic cookie updates | β Via API | β Via API + file |
β οΈ Version Required: Binary v0.1.12+ | Library v0.0.18+
Quick Start β
import piggy from "nothing-browser";
import { writeFileSync, readFileSync } from "fs";
await piggy.connect({
host: "http://localhost:2005",
key: "peaseernest..."
});
// Get cookies file path
const cookiesPath = await piggy.sessionCookiesPath();
console.log("Cookies file:", cookiesPath);
// "/home/user/my-scraper/cookies.json"
// Read current cookies
const currentCookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
console.log(`Loaded ${currentCookies.length} cookies`);
// Add a new cookie manually
const newCookies = [
...currentCookies,
{
name: "session_token",
value: "abc123def456",
domain: ".example.com",
path: "/",
secure: true,
httpOnly: true,
expires: Math.floor(Date.now() / 1000) + 86400 // 24 hours
}
];
writeFileSync(cookiesPath, JSON.stringify(newCookies, null, 2));
// Hot reload β applies without restart!
await piggy.sessionReload();
console.log("β
New cookie loaded, browser using it now");2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
cookies.json File Format β
[
{
"name": "session_id",
"value": "abc123def456",
"domain": ".example.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "Lax",
"expires": 1735689600
},
{
"name": "user_pref",
"value": "dark_mode",
"domain": "example.com",
"path": "/settings",
"secure": false,
"httpOnly": false,
"expires": null
}
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Cookie Field Reference β
| Field | Type | Required | Description |
|---|---|---|---|
name | string | β Yes | Cookie name |
value | string | β Yes | Cookie value |
domain | string | β Yes | Domain (e.g., .example.com for subdomains) |
path | string | β Yes | URL path (default: "/") |
secure | boolean | β No | HTTPS only |
httpOnly | boolean | β No | Not accessible via JavaScript |
sameSite | string | β No | "Strict", "Lax", or "None" |
expires | number | β No | Unix timestamp (seconds). null or omitted = session cookie |
Hot Reload Methods β
sessionReload() β Reload cookies and profile β
// After editing cookies.json or profile.json
await piggy.sessionReload();
// Both files are reloaded simultaneously2
3
4
sessionCookiesPath() β Get cookies file path β
const cookiesPath = await piggy.sessionCookiesPath();
// "/home/user/my-scraper/cookies.json"2
sessionPaths() β Get all file paths β
const paths = await piggy.sessionPaths();
console.log(paths.cookies); // cookies.json path
console.log(paths.profile); // profile.json path2
3
Real-World Examples β
1. Session Rotation Without Restart β
import { readFileSync, writeFileSync } from "fs";
const SESSIONS = [
{ name: "user1", token: "token_abc123" },
{ name: "user2", token: "token_def456" },
{ name: "user3", token: "token_ghi789" }
];
const cookiesPath = await piggy.sessionCookiesPath();
for (const session of SESSIONS) {
console.log(`π Switching to: ${session.name}`);
// Read current cookies
let cookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
// Update session cookie
const sessionCookie = cookies.find(c => c.name === "session_token");
if (sessionCookie) {
sessionCookie.value = session.token;
} else {
cookies.push({
name: "session_token",
value: session.token,
domain: ".example.com",
path: "/"
});
}
// Write and reload
writeFileSync(cookiesPath, JSON.stringify(cookies, null, 2));
await piggy.sessionReload();
// Now browser is logged in as this user
await piggy.site.navigate("https://example.com/dashboard");
const userName = await piggy.site.fetchText(".user-name");
console.log(`Logged in as: ${userName}`);
await piggy.site.wait(2000);
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2. Add Authentication Cookie Mid-Scrape β
// Start scraping without auth
await piggy.register("api", "https://api.example.com");
await piggy.api.navigate("https://api.example.com/public-data");
const publicData = await piggy.api.evaluate(() => ({ ... }));
// Later, we get auth token from somewhere
const authToken = await getAuthToken(); // From database, another service, etc.
// Add auth cookie without restarting
const cookiesPath = await piggy.sessionCookiesPath();
let cookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
cookies.push({
name: "auth_token",
value: authToken,
domain: ".api.example.com",
path: "/",
secure: true,
httpOnly: true
});
writeFileSync(cookiesPath, JSON.stringify(cookies, null, 2));
await piggy.sessionReload();
// Now access authenticated endpoints
await piggy.api.navigate("https://api.example.com/private-data");
const privateData = await piggy.api.evaluate(() => ({ ... }));2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
3. Bulk Cookie Import from Another Browser β
// Export cookies from Chrome (using browser extension or devtools)
// Save as chrome-cookies.json
import { readFileSync, writeFileSync } from "fs";
const chromeCookies = JSON.parse(readFileSync("./chrome-cookies.json", "utf-8"));
const cookiesPath = await piggy.sessionCookiesPath();
// Convert Chrome format to Piggy format
const piggyCookies = chromeCookies.map(c => ({
name: c.name,
value: c.value,
domain: c.domain,
path: c.path || "/",
secure: c.secure || false,
httpOnly: c.httpOnly || false,
sameSite: c.sameSite || "Lax",
expires: c.expirationDate || null
}));
// Write and reload
writeFileSync(cookiesPath, JSON.stringify(piggyCookies, null, 2));
await piggy.sessionReload();
console.log(`β
Imported ${piggyCookies.length} cookies from Chrome`);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
4. Clear All Cookies via File β
const cookiesPath = await piggy.sessionCookiesPath();
// Write empty array
writeFileSync(cookiesPath, JSON.stringify([], null, 2));
await piggy.sessionReload();
console.log("πͺ All cookies cleared");2
3
4
5
6
7
5. Backup and Restore Cookies β
import { readFileSync, writeFileSync, existsSync } from "fs";
const cookiesPath = await piggy.sessionCookiesPath();
// Backup current cookies
const backupPath = `./cookies-backup-${Date.now()}.json`;
const currentCookies = readFileSync(cookiesPath, "utf-8");
writeFileSync(backupPath, currentCookies);
console.log(`πΎ Backed up to: ${backupPath}`);
// ... do something that changes cookies ...
// Restore from backup
if (existsSync(backupPath)) {
const backupCookies = readFileSync(backupPath, "utf-8");
writeFileSync(cookiesPath, backupCookies);
await piggy.sessionReload();
console.log("π Cookies restored from backup");
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
6. Live Cookie Monitor β
import { watch } from "fs";
const cookiesPath = await piggy.sessionCookiesPath();
// Watch for external changes to cookies.json
watch(cookiesPath, async (eventType) => {
if (eventType === "change") {
console.log("π cookies.json changed externally");
// Reload automatically
await piggy.sessionReload();
const newCookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
console.log(`πͺ Now have ${newCookies.length} cookies`);
}
});
console.log("π Monitoring cookies.json for changes...");2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
7. Session Fix for Expired Cookies β
async function ensureValidSession() {
const cookiesPath = await piggy.sessionCookiesPath();
let cookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
const sessionCookie = cookies.find(c => c.name === "session_id");
// Check if expired
if (sessionCookie?.expires && sessionCookie.expires < Date.now() / 1000) {
console.log("β οΈ Session expired! Refreshing...");
// Get new session token (e.g., from refresh endpoint)
const newToken = await refreshAuthToken();
// Update cookie
sessionCookie.value = newToken;
sessionCookie.expires = Math.floor(Date.now() / 1000) + 86400; // 24 hours
writeFileSync(cookiesPath, JSON.stringify(cookies, null, 2));
await piggy.sessionReload();
console.log("β
Session refreshed");
return true;
}
return false;
}
// Check before each critical operation
await ensureValidSession();
await piggy.site.navigate("https://example.com/dashboard");2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Automatic Cookie Persistence β
Piggy automatically saves cookies to cookies.json when:
- Cookies are set via
cookie.set()API - Cookies are deleted via
cookie.delete()API - Browser sets cookies normally (from website responses)
You don't need to manually write the file for normal browsing β Piggy handles it.
// These automatically update cookies.json
await piggy.site.cookies.set("session", "abc123", ".example.com");
await piggy.site.cookies.delete("tracking_id");
// No need to call sessionReload() β already saved!2
3
4
5
You only need manual sessionReload() when:
- You edit
cookies.jsondirectly with an external editor - You programmatically write to the file (as in examples above)
- You want to reload
profile.jsonchanges
File Watcher (Automatic Reload) β
Piggy watches cookies.json and profile.json automatically using QFileSystemWatcher.
// No code needed β just edit the file and save
// Piggy detects the change and reloads automatically2
# Edit cookies.json with any editor
nano cookies.json
# Save β Piggy reloads within milliseconds
# No sessionReload() call needed!2
3
4
5
File watcher behavior:
| Action | Piggy Response |
|---|---|
Save cookies.json | Auto-reloads cookies |
Save profile.json | Auto-reloads profile |
| Delete file | Ignores (no crash) |
| Malformed JSON | Logs error, keeps previous state |
Cookie Expiration β
Session Cookies (No Expiry) β
{
"name": "session_id",
"value": "abc123",
"expires": null
}2
3
4
5
Session cookies last until the browser closes.
Persistent Cookies (With Expiry) β
{
"name": "remember_me",
"value": "xyz789",
"expires": 1735689600 // Unix timestamp (seconds)
}2
3
4
5
Set Expiration in Code β
// 7 days from now
const sevenDays = Math.floor(Date.now() / 1000) + (7 * 24 * 60 * 60);
await piggy.site.cookies.set("remember_token", "xyz789", ".example.com", "/", {
expires: sevenDays
});2
3
4
5
6
Security Considerations β
β οΈ Don't Commit cookies.json to Git β
# .gitignore
cookies.json
*.piggy
ws.json
pings.json2
3
4
5
β οΈ Cookies Contain Sensitive Data β
{
"name": "session_token",
"value": "secret_auth_token_here", // β sensitive!
"domain": ".bank.com"
}2
3
4
5
Best practices:
- Never share
cookies.json - Use environment variables for initial auth
- Delete sensitive cookies when done
Encrypt Cookies File (Advanced) β
import crypto from "crypto";
import { readFileSync, writeFileSync } from "fs";
const ENCRYPTION_KEY = process.env.COOKIE_ENCRYPTION_KEY; // 32 bytes
function encryptCookies(cookies: any[], key: Buffer) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
const encrypted = Buffer.concat([
cipher.update(JSON.stringify(cookies), "utf8"),
cipher.final()
]);
const authTag = cipher.getAuthTag();
return JSON.stringify({ iv: iv.toString("hex"), authTag: authTag.toString("hex"), data: encrypted.toString("hex") });
}
// Write encrypted
const encrypted = encryptCookies(cookies, ENCRYPTION_KEY);
writeFileSync("./cookies.enc", encrypted);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
API Reference β
Cookie Methods β
| Method | Description |
|---|---|
sessionCookiesPath() | Get path to cookies.json |
sessionReload() | Hot reload cookies and profile |
sessionPaths() | Get all file paths |
cookies.set() | Set cookie (auto-saves to file) |
cookies.get() | Get cookie by name |
cookies.delete() | Delete cookie (auto-saves to file) |
cookies.list() | List all cookies |
Troubleshooting β
"Cookies not persisting across restarts" β
Cause: cookies.json not being written
Fix:
// Ensure you're using persistent profile
const profile = await piggy.sessionProfilePath();
console.log("Profile path:", profile); // Should be in working directory2
3
"sessionReload() not applying changes" β
Cause: Malformed JSON in cookies.json
Fix:
# Validate JSON
cat cookies.json | jq .
# If invalid, fix or delete (Piggy will create fresh)
rm cookies.json2
3
4
5
"Cookies file getting too large" β
Cause: Too many cookies accumulated
Fix:
// Clean expired cookies
const cookiesPath = await piggy.sessionCookiesPath();
let cookies = JSON.parse(readFileSync(cookiesPath, "utf-8"));
const now = Date.now() / 1000;
cookies = cookies.filter(c => !c.expires || c.expires > now);
writeFileSync(cookiesPath, JSON.stringify(cookies, null, 2));
await piggy.sessionReload();2
3
4
5
6
7
8
"Cookies from file not appearing in browser" β
Cause: Domain mismatch
Fix: Ensure domain matches exactly:
// β
Correct β matches site
{ "domain": ".example.com" }
// β Wrong β won't apply
{ "domain": "example" }2
3
4
5
Next Steps β
- Identity & Profile β Understand fingerprint files
- Session Persistence β Save WebSocket frames and pings
- Remote Deployment β Run Piggy on a VPS
Nothing Ecosystem Β· Ernest Tech House Β· Kenya Β· 2026