Automatisation de navigateur avec Vercel Sandbox
Exécutez agent-browser + Chrome headless dans des microVM Vercel Sandbox éphémères. Une VM Linux est lancée à la demande, exécute les commandes du navigateur, puis s'arrête. Fonctionne avec n'importe quel framework déployé sur Vercel (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.).
Dépendances
pnpm add @agent-browser/sandbox @vercel/sandbox
La VM Sandbox a besoin des dépendances système pour Chromium ainsi que d'agent-browser lui-même. Les helpers @agent-browser/sandbox les installent par défaut pour les sandbox fraîches et utilisent des snapshots de sandbox (ci-dessous) pour un démarrage inférieur à la seconde. Passez installSystemDependencies: false uniquement si l'image du sandbox fournit déjà les bibliothèques requises par Chromium.
Pattern principal
import {
createAgentBrowserSnapshot,
runAgentBrowserCommand,
withAgentBrowserSandbox,
type VercelSandboxSession,
} from "@agent-browser/sandbox/vercel";
async function withBrowser<T>(
fn: (sandbox: VercelSandboxSession) => Promise<T>,
): Promise<T> {
return withAgentBrowserSandbox(fn);
}
Capture d'écran
La commande screenshot --json enregistre dans un fichier et renvoie le chemin. Relisez le fichier en base64 :
export async function screenshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [
"get", "title",
]);
const title = titleResult.json?.data?.title || url;
const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [
"screenshot",
]);
const ssPath = ssResult.json?.data?.path;
if (!ssPath) throw new Error("La capture d'écran n'a pas renvoyé de chemin de fichier.");
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { title, screenshot };
});
}
Snapshot d'accessibilité
export async function snapshotUrl(url: string) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [
"get", "title",
]);
const title = titleResult.json?.data?.title || url;
const snapResult = await runAgentBrowserCommand(sandbox, ["snapshot", "-i", "-c"], {
json: false,
});
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { title, snapshot: snapResult.stdout };
});
}
Workflows multi-étapes
Le sandbox persiste entre les commandes, vous pouvez donc exécuter des séquences d'automatisation complètes :
export async function fillAndSubmitForm(
url: string,
data: Record<string, string>,
postSubmitWaitArgs: string[],
) {
return withBrowser(async (sandbox) => {
await runAgentBrowserCommand(sandbox, ["open", url]);
const snapResult = await runAgentBrowserCommand(sandbox, ["snapshot", "-i"], {
json: false,
});
const snapshot = snapResult.stdout;
// Analyser le snapshot pour trouver les références des éléments...
for (const [ref, value] of Object.entries(data)) {
await runAgentBrowserCommand(sandbox, ["fill", ref, value]);
}
await runAgentBrowserCommand(sandbox, ["click", "@e5"]);
// Passez une attente spécifique à l'application, comme ["--url", "**/checkout/complete"],
// ["--text", "Merci"], ou ["#confirmation"].
await runAgentBrowserCommand(sandbox, ["wait", ...postSubmitWaitArgs]);
const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [
"screenshot",
]);
const ssPath = ssResult.json?.data?.path;
if (!ssPath) throw new Error("La capture d'écran n'a pas renvoyé de chemin de fichier.");
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
const screenshot = (await b64Result.stdout()).trim();
await runAgentBrowserCommand(sandbox, ["close"], { json: false });
return { screenshot };
});
}
Snapshots de Sandbox (Démarrage rapide)
Un snapshot de sandbox est une image VM sauvegardée d'un Vercel Sandbox avec les dépendances système + agent-browser + Chromium déjà installés. Considérez-le comme une image Docker : au lieu d'installer les dépendances à partir de zéro à chaque fois, le sandbox démarre à partir de l'image pré-construite.
Ceci n'est pas lié à la fonctionnalité de snapshot d'accessibilité d'agent-browser (agent-browser snapshot), qui extrait l'arbre d'accessibilité d'une page. Un snapshot de sandbox est un concept d'infrastructure Vercel pour un démarrage rapide de VM.
Sans snapshot de sandbox, chaque exécution installe les dépendances système + agent-browser + Chromium (~30s). Avec un snapshot, le démarrage est inférieur à la seconde.
Création d'un snapshot de sandbox
Le snapshot doit inclure les dépendances système (via dnf), agent-browser et Chromium :
const snapshotId = await createAgentBrowserSnapshot();
Exécutez-le une fois, puis définissez la variable d'environnement :
AGENT_BROWSER_SNAPSHOT_ID=snap_xxxxxxxxxxxx
Un script d'aide est disponible dans l'application de démonstration :
npx tsx examples/environments/scripts/create-snapshot.ts
Recommandé pour tout déploiement en production utilisant le pattern Sandbox.
Authentification
Sur les déploiements Vercel, le SDK Sandbox s'authentifie automatiquement via OIDC. Pour le développement local ou un contrôle explicite, définissez :
VERCEL_TOKEN=<personal-access-token>
VERCEL_TEAM_ID=<team-id>
VERCEL_PROJECT_ID=<project-id>
Ces valeurs sont passées aux appels Sandbox.create(). En leur absence, le SDK utilise VERCEL_OIDC_TOKEN (automatique sur Vercel).
Workflows planifiés (Cron)
Combinez avec les Cron Jobs Vercel pour des tâches de navigateur récurrentes :
// app/api/cron/route.ts (ou équivalent dans votre framework)
export async function GET() {
const result = await withBrowser(async (sandbox) => {
await sandbox.runCommand("agent-browser", ["open", "https://exemple.com/tarifs"]);
const snap = await sandbox.runCommand("agent-browser", ["snapshot", "-i", "-c"]);
await sandbox.runCommand("agent-browser", ["close"]);
return await snap.stdout();
});
// Traiter les résultats, envoyer des alertes, stocker des données...
return Response.json({ ok: true, snapshot: result });
}
// vercel.json
{ "crons": [{ "path": "/api/cron", "schedule": "0 9 * * *" }] }
Variables d'environnement
| Variable | Requise | Description |
|---|---|---|
AGENT_BROWSER_SNAPSHOT_ID | Non (mais recommandée) | ID du snapshot de sandbox pré-construit pour un démarrage inférieur à la seconde (voir ci-dessus) |
VERCEL_TOKEN | Non | Jeton d'accès personnel Vercel (pour le développement local ; OIDC est automatique sur Vercel) |
VERCEL_TEAM_ID | Non | ID de l'équipe Vercel (pour le développement local) |
VERCEL_PROJECT_ID | Non | ID du projet Vercel (pour le développement local) |
Exemples par framework
Le pattern fonctionne de manière identique d'un framework à l'autre. La seule différence est l'emplacement du code serveur :
| Framework | Emplacement du code serveur |
|---|---|
| Next.js | Actions serveur, routes API, gestionnaires de route |
| SvelteKit | +page.server.ts, +server.ts |
| Nuxt | server/api/, server/routes/ |
| Remix | Fonctions loader, action |
| Astro | Frontmatter .astro, routes API |
Exemple
Consultez examples/environments/ dans le dépôt agent-browser pour une application fonctionnelle utilisant le pattern Vercel Sandbox, incluant un script de création de snapshot de sandbox, une interface utilisateur de progression en streaming et une limitation de débit.