Automatizzare i profili del browser con un'API locale

Avvia un profilo da uno script, ottieni un endpoint di debug e collega Playwright o Puppeteer a un browser che ha già la sua identità e il suo proxy.
Automatizzare un browser antidetect viene di solito presentato come un problema difficile. Non lo è, a patto che lo strumento ti consegni l'unica cosa che la tua libreria di automazione sa già usare: un endpoint di debug.
La struttura
PowerOps esegue un'API HTTP legata all'indirizzo di loopback. Il tuo script le chiede di avviare un profilo; lei lancia il browser con l'identità, lo storage e il proxy di quel profilo già applicati e restituisce l'endpoint WebSocket del browser in esecuzione. Il tuo script si connette a quell'endpoint con Playwright, Puppeteer o qualsiasi altro strumento che parli il protocollo DevTools.
La libreria di automazione non ha mai bisogno di sapere che cosa sia un fingerprint. Quando si connette, l'ambiente è già stabilito.
Avviare un profilo
curl -s -H "Authorization: Bearer $POWEROPS_API_KEY" \
http://127.0.0.1:50326/status
Ogni route, tranne il controllo di stato, richiede una chiave bearer. Avviare un browser restituisce l'endpoint a cui collegarsi:
curl -s -X POST \
-H "Authorization: Bearer $POWEROPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"profileId": "..."}' \
http://127.0.0.1:50326/browser/start
Collegare la tua libreria
import { chromium } from "playwright";
const res = await fetch("http://127.0.0.1:50326/browser/start", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.POWEROPS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ profileId }),
});
const { ws } = await res.json();
// The profile's identity, storage and proxy are already in place.
const browser = await chromium.connectOverCDP(ws);
const [context] = browser.contexts();
const page = context.pages()[0] ?? await context.newPage();
await page.goto("https://example.com");
La riga importante è il commento. Nel tuo script non c'è alcuna configurazione del fingerprint, perché configurare l'ambiente non è compito dello script. Appartiene al profilo e resta lo stesso sia che il profilo venga aperto da una persona che clicca su una riga, sia da un job pianificato alle tre di notte.
Che cosa copre l'API
- La route di stato è un controllo di integrità, e l'unica che non richiede una chiave.
- Le route del browser avviano, fermano e interrogano i browser attualmente in esecuzione.
- Le route dei profili creano, aggiornano, interrogano ed eliminano i profili.
- Le route dei proxy gestiscono la libreria dei proxy e assegnano le rotte.
- Le route dei gruppi organizzano i profili in blocco.
- Le route delle estensioni importano e assegnano le estensioni.
Come viene mantenuta locale
Un'API che pilota browser con account già connessi merita due parole sui suoi confini.
- Si lega a 127.0.0.1. Nessuna impostazione la fa ascoltare su un'altra interfaccia.
- Su ogni route, tranne il controllo di stato, è richiesta una chiave bearer.
- Convalida l'header Host e non invia header CORS, così una pagina web aperta nel tuo browser di tutti i giorni non può raggiungerla.
- I segreti sono in sola scrittura: le password dei profili, i segreti dell'autenticazione a due fattori e le password dei proxy non vengono mai restituiti da una route di interrogazione.
Uno schema da copiare
Interroga i profili di un gruppo, avviali uno per uno, fai il lavoro, fermali. Eseguili pochi alla volta anziché tutti insieme. Il vincolo è la memoria della tua macchina, dato che ogni profilo è un vero processo del browser.
const { profiles } = await api("/profiles?groupId=" + groupId);
for (const batch of chunk(profiles, 5)) {
await Promise.all(batch.map(async (profile) => {
const { ws } = await api("/browser/start", { profileId: profile.id });
try {
await doTheWork(ws);
} finally {
await api("/browser/stop", { profileId: profile.id });
}
}));
}
Fermare il profilo in un `finally` conta più di quanto sembri: una chiusura pulita è ciò che scrive lo stato del browser, e un profilo terminato forzatamente a metà sessione può perdere la sessione appena stabilita.
