Date: 03-02-2026 Status: PROPOSITION Complexité: HAUTE (WebRTC/WebSocket streaming)
Quand le browser-connector rencontre un anti-robot (CAPTCHA image, slider, puzzle, reCAPTCHA, etc.), l'automation est bloquée. Il faut permettre à l'utilisateur d'intervenir manuellement.
┌─────────────────────────────────────────────────────────────────────────────┐
│ CAPTCHA ASSIST - Flux Temps Réel │
│ │
│ ┌─────────────┐ WebSocket ┌─────────────────┐ │
│ │ Frontend │◄──────────────────►│ Browser-Connector│ │
│ │ (Overlay) │ frames + events │ (Playwright) │ │
│ └─────────────┘ └─────────────────┘ │
│ │ │ │
│ │ User clicks/drags │ Screenshot stream │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Canvas │ │ Page.screenshot │ │
│ │ Interactif │ │ (zone CAPTCHA) │ │
│ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
page.mouse.click(x, y) ou page.mouse.move() + drag// Démarrer une session d'assistance CAPTCHA
POST /api/captcha-assist/start
{
"service": "linkedin",
"region"?: { "x": 100, "y": 200, "width": 400, "height": 300 }, // Zone CAPTCHA
"selector"?: ".captcha-container" // Ou auto-detect
}
// Response: { "sessionId": "xxx", "wsUrl": "wss://browser.33800.../captcha/xxx" }
// WebSocket: /api/captcha-assist/:sessionId
// Server → Client: { "type": "frame", "image": "base64...", "timestamp": 123 }
// Client → Server: { "type": "click", "x": 150, "y": 80 }
// Client → Server: { "type": "drag", "from": { "x": 50, "y": 50 }, "to": { "x": 200, "y": 50 } }
// Client → Server: { "type": "done" } // User indique qu'il a fini
// Server → Client: { "type": "resolved", "success": true }
// Terminer la session
POST /api/captcha-assist/end
{
"sessionId": "xxx"
}
// CaptchaAssist.tsx
interface CaptchaAssistProps {
sessionId: string;
onResolved: () => void;
onCancel: () => void;
}
// Affiche:
// - Canvas avec le stream de la zone CAPTCHA
// - Curseur synchronisé
// - Boutons: "J'ai fini" / "Annuler"
// - Instructions selon type CAPTCHA détecté
| Type | Interaction | Détection |
|---|---|---|
| Image select | Clicks multiples | Grille d'images visible |
| Slider | Drag horizontal | Slider element |
| Puzzle | Drag pièce vers trou | Canvas puzzle |
| reCAPTCHA v2 | Checkbox + images | iframe recaptcha |
| hCaptcha | Images | iframe hcaptcha |
| Texte | Type text | Input + image distordue |
// Dans le scraper, après chaque action:
async function checkForCaptcha(page: Page): Promise<CaptchaInfo | null> {
// Patterns connus
const captchaSelectors = [
'iframe[src*="recaptcha"]',
'iframe[src*="hcaptcha"]',
'.captcha-container',
'#captcha',
'[class*="captcha"]',
'.challenge-container'
];
for (const selector of captchaSelectors) {
const el = await page.$(selector);
if (el) {
const bbox = await el.boundingBox();
return { type: 'detected', selector, bbox };
}
}
// Ou via AI (YOLO trained on CAPTCHA patterns)
// ...
return null;
}
Quand un CAPTCHA est détecté:
// Dans browser_credentials ou settings séparées
{
"captcha_handling": "pause_and_notify" | "auto_solve" | "fail",
"captcha_timeout": 300000, // 5 min pour résoudre
"notify_channels": ["push", "webhook"],
"webhook_url": "https://..."
}
| Aspect | Difficulté | Notes |
|---|---|---|
| Screenshot streaming | Moyenne | 5-10 fps via WebSocket, base64 PNG |
| Synchronisation events | Haute | Latence réseau, coords précises |
| Détection CAPTCHA | Moyenne | Patterns connus + fallback AI |
| UX mobile | Haute | Touch events, petit écran |
| Performance | Moyenne | Compression images, throttling |
Si le streaming temps réel est trop complexe, on peut commencer par:
→ Plus lent mais beaucoup plus simple à implémenter.
Recommandation: Implémenter V1 d'abord (screenshots rafraîchis), puis V2 si besoin de fluidité.
En attente de validation avant implémentation.