L'API de password.es répond : comment s'en servir

Publié le par David Carrero

Ce blog répète la même chose depuis des mois : votre mot de passe ne devrait jamais quitter votre navigateur. Le générateur tire son hasard de crypto.getRandomValues() sur votre propre machine, et le vérificateur analyse ce que vous tapez sans l’envoyer nulle part.

Et aujourd’hui nous publions une API qui génère des mots de passe sur un serveur.

La contradiction est évidente et nous n’allons pas la maquiller : chaque réponse de l’API porte un avertissement qui dit exactement cela. Mais il existe des endroits où il n’y a pas de navigateur — un script qui provisionne cent comptes, un serveur qui fabrique un identifiant temporaire, un assistant à qui l’on demande un mot de passe et qui l’invente — et là, l’alternative n’est pas « le navigateur » : c’est un random() mal choisi ou une chaîne tapée à la main. C’est à cela que sert cette API.

L’appel en entier

Sans clé, sans inscription, sans en-têtes. C’est tout :

curl -X POST https://api.password.es/v1/generate

Elle renvoie un mot de passe de 16 caractères et son analyse. Exécuté pendant l’écriture de ce paragraphe : x*7$9,BUy9PPvOI?, tiré d’un alphabet de 89 caractères, 103,6 bits d’entropie et un temps de cassage de 2,5 × 10¹¹ ans. Niveau 4 sur 4.

Aucun de ces chiffres n’est nouveau. Ils sortent du même moteur que la jauge de la page d’accueil : la même formule de bits, le même modèle d’attaque — 10¹² tentatives par seconde, hors ligne, hachage rapide — et la même échelle de niveau que le vérificateur. Si le site et l’API donnaient des chiffres différents pour le même mot de passe, l’un des deux mentirait.

Ce qu’elle renvoie, champ par champ

La réponse contient passwords — toujours un tableau, même si vous n’en demandez qu’un — et un bloc analysis avec length, pool, bits, log10_guesses, crack_time_log10_seconds, crack_time, level, level_scale et ceiling.

Deux d’entre eux méritent un paragraphe. level_scale dit d’où vient le niveau (aujourd’hui toujours "time"), pour qu’une future divergence entre le site et l’API se voie dans le champ au lieu de devoir être déduite en comparant des chiffres. Et ceiling dit si le chiffre est exact ou un plafond : dans generate il vaut toujours false, parce que c’est le serveur qui a fabriqué le mot de passe et qui sait avec quel alphabet ; dans le vérificateur du site ce n’est pas toujours possible, parce que là c’est vous qui apportez le mot de passe.

Vient ensuite notice, l’avertissement, et un bloc _meta avec le plan, la langue appliquée, les limites et un lien vers la documentation.

Les options

Toutes optionnelles, et nommées en anglais parce que celui qui intègre une API recopie les noms de champs tels quels : length (4–64, 16 par défaut), count (1–20), lower, upper, digits, symbols, exclude_ambiguous, no_repeats et lang.

curl -X POST https://api.password.es/v1/generate -H 'content-type: application/json' -d '{"length":20,"exclude_ambiguous":true}'

Deux détails que la documentation précise et qu’il vaut mieux connaître avant d’intégrer. exclude_ambiguous retire six caractères, pas sept : il écarte 0 O 1 I l | o, mais la barre verticale ne faisait pas partie du jeu de symboles au départ, donc l’alphabet passe de 89 à 83 et non à 82. C’est pour cela que la réponse affiche pool 83. Et no_repeats n’est pas une garantie absolue : il réessaie dix fois, exactement comme le générateur du site, et à 64 caractères une répétition contiguë passe environ 0,1 % du temps. Le dire est plus utile que promettre le contraire.

La langue

Par défaut elle répond en anglais, ce qu’attend celui qui intègre sans rien préciser. Cela se change avec ?lang= dans l’URL, avec "lang" dans le corps ou avec l’en-tête Accept-Language, et en cas de désaccord c’est le premier qui gagne. Une langue inconnue n’est pas une erreur : elle retombe sur l’anglais.

Il y a ici une asymétrie qui ne se devine pas, et c’est pourquoi l’API la déclare : les messages existent en anglais et en espagnol ; les liens, dans les dix-huit langues du site. Demander l’allemand donne des liens en allemand et des messages encore en anglais. Rien à supposer : _meta.lang renvoie { "messages", "links" } avec ce qui a été appliqué à chaque moitié.

Le serveur MCP

MCP est le protocole avec lequel un assistant — Claude, ChatGPT — utilise des outils externes. https://api.password.es/mcp est un serveur MCP sans inscription et sans clé, et il publie un seul outil : generate_password, avec les mêmes paramètres que ci-dessus.

C’est la partie qui nous importe le plus, et pas pour des raisons techniques : un assistant qui n’a nulle part où prendre un mot de passe l’invente, et ce qui en sort n’est pas aléatoire, c’est ce que le modèle considère comme ayant l’allure d’un mot de passe. Avec le serveur connecté, il cesse d’improviser et renvoie un mot de passe fabriqué avec crypto.getRandomValues(), avec son analyse et avec l’avertissement inclus dans la description de l’outil et dans chaque résultat. Cet avertissement est précisément ce que l’assistant finit par lire à celui qui a demandé le mot de passe, et c’est pour cela qu’il est là.

Si vous venez d’autres serveurs MCP, une seule chose à savoir : celui-ci est sans état. Le POST reçoit une réponse JSON et n’ouvre aucun flux, Mcp-Session-Id n’est ni émis ni attendu, une notification reçoit un 202 sans corps et le GET renvoie 405. La spécification 2025-06-18 le permet explicitement, mais qui s’attend à des sessions et à du SSE débuguera à l’aveugle si personne ne le lui dit.

Ce qu’elle ne fait pas

/v1/check renvoie 501. Ce n’est ni un oubli ni un point d’entrée à moitié fait : c’est délibéré, et sa propre réponse explique pourquoi. Renvoyer les mêmes chiffres que le vérificateur exige le même moteur de motifs que celui qui tourne sur le site, et cela coûte entre 11 ms et 3,6 s de CPU par requête selon ce qu’on lui envoie. Sur un service sans inscription et sans clé, cet écart est une décision produit — où placer le plafond de longueur — qui n’est pas encore prise. En attendant, le 501 porte un checker_url qui pointe vers le vérificateur du site dans la langue demandée, lequel fait exactement cela sans rien envoyer.

Il n’y a pas non plus de comptes, ni de clés, ni de forfaits. Et comme ils n’existent pas, il n’y a pas un seul lien vers une inscription dans toute l’API : même pas dans l’erreur de limite dépassée, là où tout le monde en met un.

Les limites

Une seule, et c’est celle qui est réellement appliquée : 60 requêtes par minute et par IP. Inutile de croire cette page : le chiffre voyage dans chaque réponse, dans _meta.limits.burst. En cas de dépassement, c’est un 429 avec Retry-After et des en-têtes RateLimit-*.

Dans _meta vous verrez aussi un bloc quota avec ses valeurs à null. C’est l’emplacement réservé pour le jour où les comptes existeront, et il est vide exprès : une limite annoncée et non appliquée est pire que pas de limite du tout, parce que celui qui intègre la respecte et code contre un chiffre que personne ne compte.

Et malgré tout, réfléchissez-y à deux fois

Une API qui génère des mots de passe est, au fond, un antipatron : le mot de passe circule sur le réseau et passe par une machine qui n’est pas la vôtre. Que nous ne gardions rien ne change pas la forme du problème, seulement notre part — et vous savez déjà ce que vaut une promesse que vous ne pouvez pas vérifier.

C’est pourquoi l’avertissement ne vit pas seulement sur cette page : il voyage dans chaque réponse, dans la langue demandée. Et c’est pourquoi ce paragraphe est ici et non caché à la fin de la documentation. Pour un mot de passe que vous allez utiliser vous-même, le générateur de ce site tourne entièrement dans votre navigateur et n’envoie rien. L’API est pour l’autre cas : ce qui se passe sans personne devant un écran.

Les détails tiennent en deux pages. Ce qu’est l’API explique à qui elle s’adresse, ce qui répond aujourd’hui et ce qui ne répond pas. La référence contient les neuf paramètres, tous les champs expliqués un à un, les codes d’erreur et les limites ; c’est celle qu’on ouvre à côté de son éditeur. Et si vous voulez qu’une machine la lise, il y a openapi.json.


Sources : l’API elle-même, vérifiée en production le 31 août 2026 — POST /v1/generate, POST /v1/check (501), POST /mcp et GET /openapi.json · les chiffres de l’analyse sortent du même moteur que le générateur et le vérificateur de password.es · le modèle d’attaque est de 10¹² tentatives par seconde, hors ligne et avec hachage rapide, le même que sur le reste du site · le serveur MCP implémente la spécification 2025-06-18 avec un transport Streamable HTTP sans état.

Photo de Stanislav Kondratiev · Pexels

← Retour au blog