ego (lite) è solo un browser; ego è il tuo agente personale su tutti i dispositivi.
Iscriviti alla lista d'attesa
PlaywrightstorageStateCookielocalStorageAutomazione del browserego (lite)

storageState di Playwright: cosa salva il JSON, come caricarlo e come dimostrare che ha funzionato

18 set 202611 min di lettura
Mascotte verde di ego (lite) accanto a box blu chiusi a chiave, indecisa su quale tenga lo snapshot

Un file storageState di Playwright può sembrare completo e fallire comunque nel ripristinare lo stato da cui l'app dipende davvero. I cookie possono esserci, localStorage può esserci e il JSON può sembrare validissimo, ma sessionStorage manca di default. Se l'app tiene parte della sessione lì, caricare il file in un nuovo contesto non riporta quello stato.

Questa distinzione conta perché storageState è uno snapshot, non un profilo browser completo. Playwright rende quello snapshot facile da esportare, caricare, isolare per account e verificare. Ma quando il task dipende da stato del browser che non entra pulito nel file, come sessionStorage, estensioni, un profilo già autenticato o una persona che completa l'MFA, ego (lite) prende l'altra strada: tenere l'ambiente Chromium reale al suo posto invece di ricostruirlo dal JSON.

Questa guida resta sullo snapshot: cosa contiene storageState, come generarlo e caricarlo, come tenere account e ambienti separati, e come dimostrare che lo stato ripristinato ha davvero funzionato. Loop di login e riautenticazione automatica sono un altro problema. Qui la domanda è più semplice: cosa ha davvero salvato il file, e cosa ha lasciato fuori?

Che cos'è storageState in Playwright?

storageState di Playwright è lo snapshot salvato di cookie e localStorage di un contesto browser. Lo esporti dopo che il contesto ha già lo stato che vuoi, poi semini un contesto successivo così parte con quello snapshot invece di un barattolo vuoto.

La documentazione ufficiale di autenticazione di Playwright costruisce il setup dei test su questo file. È un consumatore dello snapshot, non la definizione dello snapshot. Questa pagina resta sul file.

I muri di login su X e LinkedIn sono in scraping con IA dietro i muri di login.

Il routing dello scrape in JavaScript è in web scraping con JavaScript.

Cosa contiene davvero il file storageState?

Il file è JSON con cookies e origins. cookies è un array di oggetti cookie. origins è un array di record di origine, ciascuno con coppie name/value di localStorage. L'API storageState scrive quella forma quando passi un path, e restituisce lo stesso oggetto quando non lo fai.

ArchivioIn storageState di default?Cosa significa
cookiesOgni voce può portare name, value, domain, path, expires, httpOnly, secure e sameSite.
localStorageSì, sotto originsIndicizzato per origine. Una chiave salvata su https://quotes.toscrape.com non compare su un'altra origine.
sessionStorageNoIl JSON non ha una chiave sessionStorage di default. Una pagina ripristinata legge sessionStorage come null.

Abbiamo verificato quella forma di file il 2026-09-18 da OpenCode. Chromium headed su quotes.toscrape.com ha esportato storageState con le chiavi di primo livello cookies e origins. d05-demo era nel localStorage di origins. La stringa JSON non conteneva sessionStorage né d05-session.

OpenCode esporta storageState di Playwright accanto a Chromium headed su quotes.toscrape.com
Il passo di export: OpenCode a sinistra, Chromium indipendente a destra. Nessun form di login. Lo snapshot è preso da una pagina pubblica con chiavi fittizie.

La guida di autenticazione di Playwright menziona anche IndexedDB e passkey nello stato riutilizzato per alcuni setup. Non dare per scontato che quelle chiavi esistano perché un post le ha elencate. Apri il file che hai generato e leggi le chiavi di primo livello.

I cookie di sessione senza Expires o Max-Age sono un'altra trappola nelle directory di profilo. Quel comportamento su disco sta in sessioni browser persistenti. In un JSON storageState, la scadenza del cookie è un campo esplicito su ogni cookie. Zero o un timestamp passato è il modo in cui vedi un cookie che non sopravviverà al giorno di calendario successivo.

Come si genera storageState e come si carica?

Genera da un contesto che ha già lo stato che vuoi. Carica in un nuovo contesto prima di aprire la pagina che ne ha bisogno. Non esportare da un'origine e aspettarti il localStorage di un'altra origine.

import { chromium } from "playwright";

const browser = await chromium.launch();
const setup = await browser.newContext();
const page = await setup.newPage();
await page.goto("https://quotes.toscrape.com/");
await page.evaluate(() => {
  localStorage.setItem("d05-demo", "local-only");
  sessionStorage.setItem("d05-session", "session-only");
});
await setup.storageState({ path: "playwright/.auth/user.json" });
await setup.close();

const reused = await browser.newContext({
  storageState: "playwright/.auth/user.json",
});
const next = await reused.newPage();
await next.goto("https://quotes.toscrape.com/");
const restored = await next.evaluate(() => ({
  local: localStorage.getItem("d05-demo"),
  session: sessionStorage.getItem("d05-session"),
}));
console.log(restored);
await browser.close();

Quel frammento è l'intero meccanismo. La documentazione di autenticazione di Playwright lo avvolge in un progetto di setup così i test saltano l'UI di login. L'involucro è opzionale. Le due chiamate no.

Se l'app tiene il token di sessione solo in sessionStorage, questo file non lo porta. Copia sessionStorage con page.evaluate, tieni un processo vivo o usa un profilo reale.

Abbiamo verificato il ripristino nella stessa sessione OpenCode. Un nuovo contesto caricato da quel file ha stampato local = local-only e session = null.

OpenCode mostra localStorage ripristinato e sessionStorage vuoto accanto a Chromium headed su quotes.toscrape.com
Il controllo di ripristino: localStorage è tornato, sessionStorage no. OpenCode è a sinistra, la pagina pubblica delle citazioni a destra.

Come si dimostra che lo stato ripristinato ha avuto effetto?

Dimostra il ripristino con una chiave che hai scritto tu, o con un URL autenticato che solo i cookie salvati possono aprire. Non trattare 'manca il form di login' come prova. Anche un bug di redirect può nascondere il form.

await page.goto("https://quotes.toscrape.com/");
const local = await page.evaluate(() => localStorage.getItem("d05-demo"));
if (local !== "local-only") {
  throw new Error("storageState did not restore localStorage");
}

Per un account reale, colpisci un URL che restituisce 200 solo quando il cookie è valido, poi asserisci un'etichetta visibile di sessione avviata. Se atterri su /login, lo snapshot è stantio. La riautenticazione sta altrove. Qui ti serve solo il fallimento: questo JSON non ha ripristinato la sessione.

ControlloPassaFallisce
Chiave localStorageLegge il valore che hai salvatonull dopo il caricamento
Chiave sessionStoragenull a meno che non l'abbia copiata tuDare per scontato che sia sopravvissuta perché localStorage sì
Scadenza cookieexpires è nel futuro sui cookie che ti servonoexpires è 0 o è già passato

Come si isolano account e ambienti?

Un file per account, per ambiente, per contesto browser che intendi riutilizzare. Mischiare cookie di staging e produzione in user.json è il modo in cui testi il tenant sbagliato.

Gli origins nel JSON sono delimitati per origine. Una chiave localStorage salvata su https://quotes.toscrape.com non compare su http://quotes.toscrape.com. Contano schema, host e porta.

playwright/.auth/staging-admin.json
playwright/.auth/staging-viewer.json
playwright/.auth/prod-readonly.json

I worker in parallelo hanno bisogno ciascuno del proprio file o del proprio contesto. Condividere un JSON tra due contesti che poi riscrivono è una race. Esporta dopo il setup, carica in sola lettura durante l'esecuzione e scrivi un file nuovo solo da un job dedicato di refresh.

Come si capisce che lo stato salvato è scaduto?

Il file può sembrare valido mentre il sito ha già revocato la sessione. Controlla expires dei cookie nel JSON, poi un URL live che richiede quel cookie.

Un cookie con expires: -1 o 0 è un cookie di sessione nello snapshot. Può funzionare nella stessa esecuzione e sparire dopo, a seconda di come lo tratta il browser. Un timestamp nel passato è già morto. Un timestamp futuro può comunque essere revocato lato server.

Il controllo live è quello che conta. Apri una rotta autenticata dopo il caricamento. Se ottieni la pagina di login, 401 o un guscio anonimo, lo snapshot è speso. Aggiorna il file. Non codificare in questa pagina una macchina login-una-volta.

Come si conserva storageState in modo sicuro?

Tratta il JSON come una password. La guida di autenticazione di Playwright stessa dice che può contenere cookie e header con cui qualcuno può fingersi te. Tienilo fuori da git, log, artefatti CI e contesto del modello.

# .gitignore
playwright/.auth/

La CI può iniettare il file da uno store di segreti all'inizio del job e cancellarlo alla fine. Non stamparlo. Non allegarlo a uno zip di test falliti. Non incollarlo in un prompt agente per 'debug della sessione'.

Quando riutilizzare un profilo browser reale?

Riutilizza un profilo Chromium reale quando l'app serve più di cookie e localStorage: estensioni, sessionStorage, segnali del dispositivo o una persona che attraversa l'MFA. Un file JSON non può portare questo.

È lì che entra ego (lite) 0.5.0.32. L'agente gira in uno Space isolato contro il profilo browser quotidiano già sulla macchina. La scheda può essere osservata, un prompt può essere preso in carico e il task può essere fermato. Il changelog di quella versione è datato 2026-09-12 su il changelog di ego (lite). Non è un esportatore di storageState. È il percorso che salta il file quando il file ha la forma sbagliata.

Abbiamo verificato quell'isolamento in ego (lite) da OpenCode. La panoramica Spaces ha tenuto il task delle citazioni nel proprio Space in esecuzione, con il resto del lavoro in un altro Space invece di ricostruire la sessione dal JSON.

OpenCode accanto alla panoramica Spaces di ego (lite) con il task storageState delle citazioni in esecuzione nel proprio Space
Il browser reale resta al suo posto. Uno Space esegue il task delle citazioni; il resto del lavoro resta in un altro Space.

Abbiamo verificato lo stesso URL pubblico dentro uno di quegli Space. Lo Space 6 è rimasto in controllo dell'agente su quotes.toscrape.com, con Take over e Stop visibili. L'ambiente del browser è rimasto al suo posto invece di essere ricostruito da uno snapshot JSON.

OpenCode guida ego-browser accanto a uno Space di ego (lite) su quotes.toscrape.com con Agent is in control, Take over e Stop
Il percorso del profilo osservato: OpenCode a sinistra, uno Space di ego (lite) a destra, ancora in controllo dell'agente sulla pagina pubblica delle citazioni.

Se localStorage torna e sessionStorage è null, il file ha fatto il suo lavoro. Non trattare un form di login assente come prova. Il 2026-09-18 il contesto ripristinato ha stampato local = local-only e session = null da chiavi fittizie, senza form password.

Quali sono le sfide e i limiti?

Il file sembra completo e perde comunque lo store che l'app usa davvero. È il fallimento di default.

Il mismatch di origine è il secondo. Salva su localhost:3000, carica contro 127.0.0.1:3000, e localStorage è vuoto mentre i cookie possono comunque attaccarsi a seconda del dominio.

Il terzo è sovraccaricare questa pagina di coreografia di login. Rilevare 401, rimbalzare su /login e aggiornare lo snapshot sono lavori veri. Non sono il lavoro di questo file.

FAQ

storageState di Playwright include i cookie?

Sì. cookies è un array di primo livello nel JSON. Ogni cookie può includere name, value, domain, path, expires, httpOnly, secure e sameSite.

storageState include localStorage?

Sì, sotto origins. Ogni record di origine tiene coppie name/value di localStorage solo per quell'origine.

storageState include sessionStorage?

Non di default. Una pagina può scrivere sessionStorage, esportare storageState e produrre comunque un JSON senza chiave sessionStorage. Il contesto ripristinato legge quello store vuoto. Il 2026-09-18 l'esecuzione headed ha ripristinato local = local-only e session = null.

Come si genera un file storageState?

Chiama await context.storageState({ path: 'playwright/.auth/user.json' }) dopo che il contesto ha già i cookie e il localStorage che vuoi.

Come si carica storageState in un nuovo contesto?

Passa storageState: 'playwright/.auth/user.json' a browser.newContext. Carica prima di navigare alla pagina che serve lo snapshot.

Come so che lo stato ripristinato ha funzionato?

Leggi una chiave localStorage che hai impostato, oppure apri un URL che solo i cookie salvati possono raggiungere. L'assenza dell'interfaccia di login non è una prova.

Devo fare commit di storageState su git?

No. Aggiungi playwright/.auth/ a .gitignore. Il file può impersonare l'account che ha catturato.

Due test possono condividere un file storageState?

Possono caricare lo stesso snapshot in sola lettura. Non lasciare che worker in parallelo scrivano lo stesso file. Usa un file per ruolo se gli account differiscono.

Quando usare un profilo browser reale?

Quando l'app serve sessionStorage, estensioni o una persona per l'MFA. ego (lite) fa quel lavoro in uno Space sul tuo profilo Chromium quotidiano.

storageState è la stessa cosa di un user data directory?

No. storageState è uno snapshot JSON. Un user data directory è il profilo su disco.

Se il task successivo serve il browser reale già autenticato invece di uno snapshot JSON, ego (lite) è scaricabile gratuitamente.