Microsoft Webwright transforme les agents web en programmeurs : même modèle IA, mais 26,6 points de succès en plus sur les longues missions. La fin des clics inutiles ?

Pendant des années, les agents web ont fonctionné clic après clic, et bien souvent, ils échouaient lamentablement sur les longues missions. Microsoft Research et l’Université de Hong Kong viennent de changer la donne avec Webwright : au lieu de faire cliquer l’IA, ils lui donnent un terminal et lui demandent d’écrire un programme. Résultat ? Le même modèle GPT-5.4 passe de 33,5% de réussite à 60,1% sur des tâches longues. Et au lieu de laisser derrière lui une trace de clics incompréhensible, il produit un outil en ligne de commande que vous pouvez réutiliser.

LES AGENTS WEB CLASSIQUES : UNE SUCCESSION DE CLICS SANS FIN

Si vous avez déjà construit un agent web, vous connaissez le scénario : vous lui donnez une tâche comme « extraire toutes les fiches de ce catalogue dans un tableau », et vous le regardez avancer centimètre par centimètre. Il lit la page. Il prédit un clic. Il attend que le DOM change, c’est-à-dire que la structure de la page telle que le navigateur la voit se mette à jour. Il relit, prédit à nouveau, attend encore.

Et puis, vers la 40ème étape, tout s’effondre. Une fenêtre modale apparaît sans prévenir. Le bouton « page suivante » se déplace. L’agent confond un élément avec un autre. Un seul de ces problèmes peut faire dérailler toute la mission. Le vrai problème n’est pas le mauvais clic. C’est la façon dont l’agent fonctionne : regarder la page, décider d’une action, voir ce qui a changé, puis décider à nouveau. Il répète cette boucle sans arrêt, sans avoir de plan durable pour terminer la tâche de A à Z.

Les agents web classiques ne voient pas plus loin que le prochain clic. Ils sont comme un robot qui avance dans le noir, sans savoir où il va.

LES SOLUTIONS EXISTANTES : MIEUX, MAIS PAS ASSEZ

Le domaine a essayé plusieurs méthodes pour rendre cette boucle plus fiable. Certains agents, comme ceux d’OpenAI Operator ou Anthropic Computer Use, travaillent à partir de captures d’écran et interagissent avec un site comme un humain le ferait. D’autres, comme WebVoyager, utilisent le DOM de la page pour comprendre quels éléments sont disponibles et décider lequel manipuler.

Les benchmarks comme Mind2Web et WebArena ont rendu ces systèmes plus faciles à comparer en fournissant aux agents un ensemble standard d’actions : cliquer, taper, faire défiler, sélectionner. Et des Outils open source comme browser-use, Skyvern, Stagehand ou LaVague ont transformé ces idées en API que les ingénieurs peuvent intégrer plus facilement dans des applications réelles.

Ces approches améliorent la fiabilité de la boucle, mais elles ne changent pas son fonctionnement de base : l’agent prend toujours une action à la fois, attend de voir ce qui se passe, puis décide quoi faire ensuite. Et quand la tâche est terminée, il n’a rien construit de réutilisable : il a seulement enchaîné une série de clics.

WEBWRIGHT : L’AGENT QUI ÉCRIT DU CODE AU LIEU DE CLIGNER DES YEUX

Webwright, un framework d’agent navigateur développé par Microsoft Research et l’Université de Hong Kong, prend une direction radicalement différente. Son slogan résume l’idée : « Un terminal, c’est tout ce dont un agent web a besoin. »

Au lieu de demander au modèle de deviner le prochain clic, Webwright fait écrire et exécuter du code aux agents : des scripts en bash et Playwright pour ouvrir les navigateurs, inspecter les pages et accomplir la tâche. Le résultat n’est pas juste une longue séquence d’actions dans le navigateur. C’est un programme que les ingénieurs peuvent inspecter, relancer, modifier et réutiliser.

Cette différence compte surtout quand le web est votre source de données : tableaux de bord, catalogues de produits, résultats de recherche, outils internes, sites bourrés de JavaScript ou workflows que vous comptez exécuter plus d’une fois. Dans ces cas, la question n’est pas seulement de savoir si un agent peut terminer la tâche. C’est de savoir s’il doit continuer à cliquer dans le navigateur ou écrire un programme réutilisable pour faire le travail.

POURQUOI ÉCRIRE DU CODE CHANGE TOUT

Le passage à l’écriture de code ne résout pas seulement les symptômes. Il s’attaque au problème de fond. Aujourd’hui, les agents web diffèrent par la façon dont ils comprennent une page : certains regardent des captures d’écran, d’autres lisent le DOM. Mais la plupart fonctionnent de la même manière : prendre une action dans le navigateur, voir ce qui se passe, puis décider de la prochaine action.

Ça marche pour les tâches courtes. Mais plus la tâche est longue, plus il y a de chances qu’un mauvais clic, un changement de page ou un élément mal interprété fasse tout échouer.

Les agents visuels sont faciles à comprendre : ils regardent la page comme une personne le ferait et décident où cliquer. Ça fonctionne bien pour beaucoup de tâches dans le navigateur, mais le scraping demande plus de cohérence. Un petit décalage dans la mise en page peut déplacer un bouton juste assez pour que l’agent clique au mauvais endroit… ou sur rien du tout.

Il y a aussi un coût à regarder sans cesse des captures d’écran. Chaque nouvelle capture consomme des tokens, et l’agent doit garder assez de contexte pour se souvenir de ce qu’il a déjà fait. Sur une longue tâche, ce contexte devient plus difficile et plus cher à maintenir.

Les agents qui utilisent le DOM et l’arbre d’accessibilité évitent certains des problèmes liés aux captures d’écran. Au lieu de deviner où se trouve un élément en se basant sur les pixels, ils peuvent lire la structure de la page et identifier directement les boutons, liens, formulaires et autres éléments. WebVoyager, par exemple, a rapporté environ 59% de réussite sur 50 sites web réels, bien mieux que les bases de référence purement textuelles.

Mais ça crée un autre problème : trop de données de page. Une page complexe peut produire un arbre d’accessibilité de plus de 50 Ko. Quand l’agent avance dans une tâche, l’ancien état de la page s’accumule dans son contexte même si une grande partie n’est plus utile. Les références qu’il utilise pour identifier les éléments peuvent aussi changer quand la page charge du contenu paresseusement, se rerend ou navigue ailleurs.

Donc, un meilleur accès à la structure de la page ne rend pas forcément les longues tâches dans le navigateur plus fiables. Sur VisualWebArena, les meilleurs agents vision-langage n’ont complété que environ 16% des tâches, contre environ 89% pour les humains.

Les API d’actions fixes ont rendu les agents web plus faciles à construire et à évaluer. On donne au modèle un petit ensemble d’actions : cliquer, taper, faire défiler, sélectionner, puis on le laisse observer le résultat et choisir à nouveau. L’inconvénient, c’est que l’agent ne peut exprimer qu’une seule petite étape à la fois. Il ne peut pas naturellement dire : « continue à cliquer sur suivant jusqu’à ce qu’il n’y ait plus de pages », « réessaye si cet élément n’apparaît pas » ou « collecte ces 1 000 lignes et sauvegarde-les dans un CSV ». Chacune de ces instructions doit être décomposée en de nombreuses actions individuelles, avec un autre appel au modèle entre chaque.

Les frameworks comme browser-use, Skyvern, Stagehand ou LaVague rendent les agents navigateurs beaucoup plus faciles à construire et à intégrer. C’est utile, mais ça ne résout pas un problème important pour le travail de données récurrent : quand la tâche est terminée, il n’y a souvent rien de réutilisable qui reste. L’agent a peut-être collecté les données une fois, mais la semaine suivante, il doit tout recommencer depuis le navigateur.

La recherche avait déjà pointé vers une autre approche. Dans l’article Executable Code Actions Elicit Better LLM Agents publié à l’ICML 2024, les chercheurs derrière CodeAct ont remplacé les actions prédéfinies, au format JSON, par du Python exécutable. Ils ont rapporté jusqu’à 20% de taux de réussite en plus tout en utilisant environ 30% d’étapes en moins.

La raison est simple : le code permet au modèle de faire plus qu’une action à la fois. Il peut utiliser des boucles, stocker des variables, réessayer en cas d’échec, écrire des fichiers et inspecter les erreurs, le tout dans un programme qu’il peut relancer. Webwright apporte cette même idée à l’automatisation navigateur.

CLICS VS CODE : QUAND LA SESSION DU NAVIGATEUR DISPARAÎT, TOUT DISPARAÎT

La plupart des agents navigateurs gardent leur progression dans la session du navigateur. Fermez l’onglet, et cet état disparaît.

Webwright fait l’inverse. Le navigateur est temporaire ; l’espace de travail local est ce qui persiste. L’agent écrit des scripts, des logs, des captures d’écran et des fichiers de sortie pendant qu’il travaille, transformant finalement une exécution réussie en un outil réutilisable. Ce changement a quelques avantages pratiques.

Les quatre avantages principaux du projet viennent de là :

La tâche : Utiliser le calculateur de compte de retraite IRA de Chase pour comparer un IRA traditionnel et un Roth IRA pour une personne de 30 ans qui prend sa retraite à 65 ans, épargne 300 dollars par mois, obtient un rendement de 3% et a des taux d’imposition de 13% aujourd’hui et 24% à la retraite.

La tâche : Rechercher sur Google Flights un voyage aller-retour de Seattle à San Francisco, en incluant les dates, et retourner les résultats classés.

C’est ce que Microsoft entend par « votre historique de navigation est du code au lieu de clics ». Une tâche terminée devient un point de départ pour la suivante, au lieu d’une session navigateur qui disparaît quand elle se termine.

LE CODE, UNE SOLUTION PLUS ROBUSTE QUE LES CLICS

Les alternatives sont utiles, mais elles placent toujours le navigateur au centre du flux de travail. Stagehand combine Playwright avec des commandes en langage naturel. agent-browser donne aux agents une CLI pour prendre de petites actions dans le navigateur. browser-use relit sans cesse la page, choisit une action et l’exécute.

Webwright prend une approche différente. Au lieu de choisir la prochaine action dans le navigateur, le modèle peut écrire un script Python complet. Le navigateur est temporaire ; le code, les logs et les sorties restent dans l’espace de travail local. Et quand la tâche est résolue, l’agent laisse derrière lui un programme qu’on peut relancer.

C’est l’idée centrale : cliquer termine la tâche une fois ; écrire du code la termine et garde la solution.

UNE IA QUI PROGRAMME : COMMENT WEBWRIGHT FONCTIONNE VRAIMENT

Alors, que faut-il pour construire un agent comme ça ? Peu de choses, en réalité.

La plupart des agents navigateurs placent un harnais — le logiciel qui connecte le modèle au navigateur — entre les deux. Ce harnais donne généralement au modèle un ensemble fixe d’actions : cliquer sur cet élément, taper dans ce champ, faire défiler la page, lire le DOM, prendre une capture d’écran.

Webwright prend une approche différente. Au lieu de donner au modèle un menu d’actions navigateur, il lui donne un terminal et le laisse décider quelles commandes exécuter.

Ça rend le système étonnamment petit. Le harnais principal fait environ 1 000 lignes de code réparties en trois composants. Le dépôt complet approche 1 500 lignes une fois qu’on inclut l’interface en ligne de commande et le support pour différents fournisseurs de modèles. Il n’y a pas de grande bibliothèque d’actions navigateur prédéfinies. Pas de moteur DOM personnalisé. Le système principal se compose juste de trois pièces :

L’interaction entre ces pièces suit une boucle simple :

comprendre l’état actuel → choisir une commande → l’exécuter → voir ce qui s’est passé → répéter

Le processus continue jusqu’à ce que le modèle estime que la tâche est terminée et qu’un auto-contrôle final soit d’accord. Webwright ne tente pas d’encoder chaque interaction navigateur possible dans le harnais. Il donne au modèle une interface généraliste — le terminal — et laisse le modèle comprendre comment l’utiliser.

LES BENCHMARKS : DES RÉSULTATS QUI PARLENT D’ELLES-MÊMES

Les benchmarks confirment la conception. Sur Online-Mind2Web, GPT-5.4 avec Webwright obtient 86,7%, le meilleur score parmi les harnais d’AutoEval open source, tandis que Claude Opus 4.7 atteint 84,7% et performe mieux sur les tâches les plus difficiles.

Le signal le plus fort vient d’Odysseys. GPT-5.4 utilisant un contrôle navigateur basé sur des coordonnées obtient 33,5%. Avec Webwright, le même modèle atteint 60,1% — un gain de 26,6 points obtenu en changeant le harnais, pas le modèle.

Changer la façon dont l’agent interagit avec le navigateur fait plus que doubler ses chances de réussite. C’est comme passer d’un vélo à une voiture : la même énergie, mais une destination atteinte bien plus souvent.

Un autre résultat confirme la thèse : une fois que Webwright a construit des outils réutilisables, le modèle peut devenir plus petit. Microsoft rapporte que même un modèle open source de 9 milliards de paramètres (Qwen-3.5-9B) performe bien sur Online-Mind2Web dès que cinq outils ou plus sont disponibles. L’outil ne se contente pas d’économiser du travail : il réduit aussi les capacités nécessaires du modèle la prochaine fois.

LES TRADE-OFFS : CE QUE ÇA COÛTE VRAIMENT

Ces scores sont des LLM-judged AutoEval, et le résultat phare de Mind2Web utilise 100 des 300 tâches. Ce n’est pas non plus bon marché : environ 2,37 dollars par tâche avec GPT-5.4 et 6,09 dollars avec Claude Opus 4.7. Webwright dépense plus de calcul au départ pour construire des outils plus robustes et réutilisables.

J’ai testé Webwright sur trois sites de plus en plus difficiles, en utilisant un agent Claude Sonnet séparé pour chaque exécution. L’objectif était de voir à quel point Webwright est robuste là où le scraping échoue habituellement.

J’ai utilisé le plugin Claude Code plutôt que le harnais de benchmark autonome. Ça garde la même configuration de base — terminal + Playwright — mais le plugin Claude Code exécute la boucle de l’agent. Ça supprime le besoin d’une clé API séparée ou d’une facture par tâche, même si ça ne supprime pas le coût de calcul.

Le trade-off, c’est l’usage des tokens. Dans l’exemple de Microsoft, la compétence hébergée par Codex a utilisé environ 3,3 millions de tokens contre 424 000 pour le harnais autonome — environ 8 fois plus, principalement à cause du contexte mis en cache. Le coût se déplace vers la session hôte plutôt que de disparaître.

playwright install firefox   # la compétence Claude Code utilise Firefox headless, ~110 Mo téléchargés une fois

TEST 1 : PAGINATION STATIQUE SUR BOOKS.TOSCRAPE.COM

books.toscrape.com est le plus simple des trois cas : 50 pages de catalogue numérotées, 20 livres par page, servies en HTML brut. La tâche consistait à extraire chaque titre de livre, prix, note, disponibilité et URL, puis à créer un CLI réutilisable avec les options --pages et --out.

Avant d’écrire le scraper, l’agent a inspecté le site et testé ses limites : la page 50 n’avait pas de lien « suivant », tandis que la page 51 retournait une erreur 404. Il a ensuite extrait les sélecteurs d’une vraie fiche produit et construit une simple boucle de pagination.

for n in range(1, pages + 1):
    url = CATALOGUEURLTEMPLATE.format(n=n)
    await page.goto(url, wait_until="domcontentloaded")
    cards = page.locator("article.product_pod")
    count = await cards.count()
    log(n, f"loaded catalogue page {n}/{pages} ({url}) -> {count} book cards found")

Un agent basé sur des clics aurait pu gérer ce site, mais le code était plus propre. Un problème subtil concernait les URLs relatives des livres, qui changent d’une page à l’autre. Au lieu de les construire manuellement, le scraper a utilisé les valeurs href résolues par le navigateur.

Le résultat n’était pas seulement des données scrapées, mais un outil CLI autonome qui pouvait être relancé sans agent.

$ python final_script.py --help
usage: final_script.py [-h] [--pages PAGES] [--out OUT]
Scrape all books listed on books.toscrape.com's catalogue pages.
  --pages PAGES  Number of catalogue pages to traverse . Default: 50.
  --out OUT      Output CSV file path . Default: books.csv.

$ python final_script.py --pages 2 --out sample.csv
-> 40 rows written to ./sample.csv

Résultat : 1 000 livres sur 50 pages, zéro champ vide, en environ 37 secondes.

L’étape de vérification a aussi repéré un bug : la première version effaçait par erreur son journal de preuves quand on lançait --help. L’agent a trouvé l’effet secondaire, corrigé le bug, testé la correction et relancé avec succès. Même sur ce site simple, l’avantage était clair : un programme débogable et réutilisable au lieu d’une trace de clics jetable.

TEST 2 : PAGES RENDUES PAR JAVASCRIPT SUR QUOTES.TOSCRAPE.COM

Le deuxième test ajoute du JavaScript. Les citations ne sont pas présentes dans le HTML brut ; elles n’apparaissent qu’après que le navigateur ait exécuté le JavaScript de la page. L’agent l’a d’abord vérifié : une requête HTTP directe retournait zéro élément de citation, tandis que la page rendue en affichait 10. Un scraper basique utilisant requests et BeautifulSoup retournerait silencieusement rien du tout.

Ça signifie que chaque page doit être rendue avant l’extraction. Il y a un autre piège : la page 11 retourne encore un code HTTP 200, donc les codes de statut ne peuvent pas indiquer au scraper quand s’arrêter. À la place, le programme vérifie le DOM en direct pour le lien « suivant » et s’arrête quand il disparaît à la page 10.

while True:
    url = BASEURL if n == 1 else PAGEURL_TEMPLATE.format(n=n)
    await page.goto(url, wait_until="domcontentloaded")
    await page.waitforselector(".quote", timeout=10000)   # attendre que JS injecte les citations
    .                                                       # lire les 10 cartes .quote rendues
    has_next = await page.locator("li.next a").count() > 0
    if not has_next or n >= pages:                           # s'arrêter sur le DOM, pas sur un code de statut
        break
    n += 1

Là encore, la sortie est devenue un CLI réutilisable avec les options --pages et --out, capable de s’exécuter sans agent.

Le code ne se contente pas d’extraire des données. Il comprend la logique du site et s’adapte à ses changements.

Résultat : 100 citations sur 10 pages en 8,9 secondes, avec zéro champ texte ou auteur vide.

L’exécution a aussi révélé une mauvaise hypothèse dans mes consignes : j’attendais deux pages pour produire 40 lignes, en reprenant le compte de 20 par page du site de livres. Ce site en sert 10, donc le résultat correct était 20. L’agent a retourné les vraies données et signalé la discordance plutôt que de forcer la sortie à correspondre au cahier des charges.

TEST 3 : FLUX À DÉFILEMENT INFINI SUR QUOTES.TOSCRAPE.COM

Le troisième test ajoute un défilement infini. L’agent a d’abord confirmé le comportement du site : has_next devient faux à la page 10, et la page 11 ne retourne aucune citation. Il a ensuite construit une boucle de défilement jusqu’à stabilité qui s’arrête quand aucun nouveau contenu n’apparaît.

for i in range(1, max_scrolls + 1):
    await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
    await page.waitfortimeout(1000)
    count = await page.locator(".quote").count()
    if count == prev_count:          # aucun nouveau contenu arrivé
        stable_iters += 1
        if stable_iters >= 2:        # s'arrêter sur stabilité, pas sur un compte fixe
            break
    else:
        stable_iters = 0
    prev_count = count

Le compte du DOM a augmenté de 10 → 20 → . → 100, est resté à 100 pendant deux défilements, et s’est arrêté à l’itération 11. L’option --max-scrolls n’était qu’une sécurité. Forcer --max-scrolls 5 a retourné exactement 60 lignes, prouvant que la condition d’arrêt répondait à la page, pas à une constante cachée.

Résultat : 100 citations en 11 itérations, prenant environ 17 secondes.

LE CODE, UNE VALEUR INESTIMABLE SUR LES SITES DIFFICILES

Sur les trois tests, la valeur du code devient évidente à mesure que les sites deviennent plus complexes. La pagination statique est simple ; le JavaScript demande un vrai navigateur ; le défilement infini exige que le programme raisonne sur quand s’arrêter.

Il y a aussi une vérification croisée utile : les tests 2 et 3 scrapent les mêmes 100 citations via deux interfaces différentes — pagination et défilement infini — et produisent des résultats identiques ligne par ligne. Ça nous donne une vérification de complétude que nous pouvons réellement comparer.

Le code ne ment pas. Quand deux méthodes différentes retournent les mêmes données, on peut être sûr que le résultat est juste.

LES TRADE-OFFS PRATIQUES : CE QU’IL FAUT SAVOIR

Il y a des compromis. La configuration a nécessité un téléchargement de Firefox d’environ 110 Mo et quelques corrections d’environnement sous Windows. Le plugin Claude Code utilise aussi un navigateur headless, ce qui peut poser problème sur certains systèmes.

Mais le plus gros inconvénient reste le coût en tokens. Dans l’exemple de Microsoft, la compétence hébergée par Codex a consommé environ 3,3 millions de tokens contre 424 000 pour le harnais autonome — soit environ 8 fois plus. Le coût se déplace de la facture API vers la session locale, mais il reste élevé.

Pourtant, quand on regarde les résultats, le jeu en vaut la chandelle. Un outil réutilisable qui fonctionne du premier coup, sans avoir à relancer un agent à chaque exécution, change la donne pour le scraping et l’automatisation.

Et puis, il y a cette satisfaction de voir l’IA écrire du code qui fait exactement ce qu’on lui demande, sans se perdre dans des clics inutiles. Le futur des agents web n’est peut-être pas dans les clics, mais dans les lignes de code.

Sources :
  • Towards Data Science

L'indépendance de CLODCO est votre garantie.

Pour que l'actualité de l'IA reste sans filtre et sans concession, votre soutien est indispensable. Votre contribution est le seul moteur de notre liberté éditoriale.

Soutenir CLODCO