Questo blog ripete da mesi la stessa cosa: la tua password non dovrebbe uscire
dal browser. Il
generatore prende il caso da crypto.getRandomValues() sulla tua
macchina e il controllo analizza quello che scrivi senza
mandarlo da nessuna parte.
E oggi pubblichiamo un’API che genera password su un server.
La contraddizione è evidente e non abbiamo intenzione di mascherarla: ogni
risposta dell’API porta un avviso che dice esattamente questo. Ma ci sono posti
dove il browser non c’è — uno script che crea cento account, un server che
produce una credenziale temporanea, un assistente a cui qualcuno chiede una
password e che se la inventa — e lì l’alternativa non è «il browser»: è un
random() scelto male o una stringa scritta a mano. Questa API serve a quello.
La chiamata intera
Senza chiave, senza registrazione, senza header. È tutta qui:
curl -X POST https://api.password.es/v1/generate
Restituisce una password di 16 caratteri e la sua analisi. Eseguita mentre si
scriveva questo paragrafo: x*7$9,BUy9PPvOI?, presa da un alfabeto di 89
caratteri, 103,6 bit di entropia e un tempo di crack di 2,5 × 10¹¹ anni.
Livello 4 su 4.
Nessuno di questi numeri è nuovo. Escono dallo stesso motore che disegna l’indicatore della home: la stessa formula dei bit, lo stesso modello di attacco — 10¹² tentativi al secondo, offline, hash veloce — e la stessa scala di livello del controllo. Se il sito e l’API dessero numeri diversi per la stessa password, uno dei due starebbe mentendo.
Cosa restituisce, campo per campo
La risposta porta passwords — sempre un array, anche se ne chiedi una sola — e
un blocco analysis con length, pool, bits, log10_guesses,
crack_time_log10_seconds, crack_time, level, level_scale e ceiling.
Due meritano un paragrafo. level_scale dice da dove viene il livello (oggi
sempre "time"), così che una futura divergenza tra il sito e l’API si veda nel
campo invece di doverla dedurre confrontando numeri. E ceiling dice se la
cifra è esatta o un tetto: in generate è sempre false, perché la password
l’ha fatta il server e sa con quale alfabeto; nel controllo del sito non sempre
può esserlo, perché lì la password la porti tu.
Poi arriva notice, l’avviso, e un blocco _meta con il piano, la lingua
applicata, i limiti e un link alla documentazione.
Le opzioni
Tutte opzionali, e con i nomi in inglese perché chi integra un’API scrive i
campi tali e quali: length (4–64, di default 16), count (1–20), lower,
upper, digits, symbols, exclude_ambiguous, no_repeats e lang.
curl -X POST https://api.password.es/v1/generate -H 'content-type: application/json' -d '{"length":20,"exclude_ambiguous":true}'
Due dettagli che la documentazione spiega e che conviene sapere prima di
integrare. exclude_ambiguous toglie sei caratteri, non sette: scarta
0 O 1 I l | o, ma la barra verticale non era nell’insieme dei simboli fin
dall’inizio, quindi l’alfabeto scende da 89 a 83 e non a 82. Per questo la
risposta dice pool 83. E no_repeats non è una garanzia assoluta: riprova
dieci volte, esattamente come il generatore del sito, e a 64 caratteri una
ripetizione contigua passa circa lo 0,1 % delle volte. Dirlo è più utile che
promettere il contrario.
La lingua
Di default risponde in inglese, che è quello che si aspetta chi integra senza
dire niente. Si cambia con ?lang= nell’URL, con "lang" nel corpo o con
l’header Accept-Language, e se sono in disaccordo vince il primo. Una lingua
che non esiste non è un errore: ricade sull’inglese.
Qui c’è un’asimmetria che non si indovina, ed è per questo che l’API la dichiara:
i messaggi esistono in inglese e spagnolo; i link, in tutte e diciotto le
lingue del sito. Chiedere il tedesco dà link in tedesco e messaggi ancora in
inglese. Non serve supporlo: _meta.lang porta { "messages", "links" } con
quello che è stato applicato a ciascuna metà.
Il server MCP
MCP è il protocollo con cui un assistente — Claude, ChatGPT — usa strumenti
esterni. https://api.password.es/mcp è un server MCP senza registrazione e
senza chiave, e pubblica un solo strumento: generate_password, con gli stessi
parametri di sopra.
È la parte che ci interessa di più, e non per ragioni tecniche: un assistente
che non ha da dove prendere una password se la inventa, e quello che ne esce
non è casuale, è ciò che il modello considera abbia la forma di una password.
Con il server collegato smette di improvvisare e ne restituisce una fatta con
crypto.getRandomValues(), con la sua analisi e con l’avviso incluso nella
descrizione dello strumento e in ogni risultato. Quell’avviso è esattamente
quello che l’assistente finisce per leggere a chi ha chiesto la password, ed è
per questo che sta lì.
Se arrivi da altri server MCP, un dato solo: questo è senza stato. Il POST
riceve una risposta JSON e non apre nessuno stream, Mcp-Session-Id non viene
né emesso né atteso, una notifica riceve 202 senza corpo e la GET restituisce
405. La specifica 2025-06-18 lo permette esplicitamente, ma chi si aspetta
sessioni e SSE finirà a debuggare alla cieca se nessuno glielo dice.
Quello che non fa
/v1/check restituisce 501. Non è una svista né un endpoint lasciato a
metà: è voluto, e la risposta stessa spiega perché. Restituire gli stessi numeri
del controllo richiede lo stesso motore di pattern che gira sul sito, e quello
costa tra 11 ms e 3,6 s di CPU per richiesta a seconda di cosa gli mandi. Su un
servizio senza registrazione e senza chiave, quella forbice è una decisione di
prodotto — dove mettere il tetto di lunghezza — che ancora non è stata presa.
Nel frattempo il 501 porta un checker_url che punta al controllo del sito
nella lingua richiesta, che fa esattamente questo senza inviare nulla.
Non esistono nemmeno gli account, né le chiavi, né i piani. E siccome non esistono, in tutta l’API non c’è un solo link a una registrazione: nemmeno nell’errore di limite superato, che è dove lo mettono tutti.
I limiti
Uno, ed è quello che viene davvero applicato: 60 richieste al minuto per IP.
Non serve credere a questa pagina: il numero viaggia dentro ogni risposta, in
_meta.limits.burst. Se lo superi arriva un 429 con Retry-After e header
RateLimit-*.
In _meta vedrai anche un blocco quota con i valori a null. È lo spazio
riservato per quando ci saranno gli account, e va vuoto di proposito: un
limite annunciato e non applicato è peggio che non annunciarne nessuno, perché
chi integra lo rispetta e programma contro un numero che nessuno sta contando.
E anche così, pensaci due volte
Un’API che genera password è, in fondo, un antipattern: la password viaggia in rete e passa da una macchina che non è la tua. Che noi non conserviamo niente non cambia la forma del problema, solo la nostra parte — e sai già quanto vale una promessa che non puoi verificare.
Per questo l’avviso non vive solo su questa pagina: viaggia in ogni risposta, nella lingua che chiedi. E per questo il paragrafo sta qui e non nascosto in fondo alla documentazione. Per una password che userai tu, il generatore di questo sito gira interamente nel tuo browser e non invia niente. L’API è per l’altra cosa: quello che succede senza nessuno davanti a uno schermo.
I dettagli stanno in due pagine. Cos’è l’API racconta per chi è,
cosa risponde oggi e cosa no. Il riferimento ha i nove
parametri, tutti i campi spiegati uno a uno, i codici di errore e i limiti; è
quella che si apre con l’editor di fianco. E se quello che vuoi è che lo legga
una macchina, c’è openapi.json.
Fonti: l’API stessa, verificata in produzione il 31 agosto 2026 —
POST /v1/generate, POST /v1/check (501), POST /mcp e GET /openapi.json ·
i numeri dell’analisi escono dallo stesso motore del generatore e del controllo
di password.es · il modello di attacco è 10¹² tentativi al secondo, offline e
con hash veloce, lo stesso del resto del sito · il server MCP implementa la
specifica 2025-06-18 con trasporto Streamable HTTP senza stato.
Foto di Stanislav Kondratiev · Pexels