# password.es API가 응답한다: 사용법

> 키도 가입도 없는 호출 한 번으로 비밀번호와 사이트에서 보던 것과 똑같은 숫자가 돌아온다. 비트, 크래킹 시간, 등급. 아직 못 하는 일과, 호출이 늘 좋은 생각은 아닌 이유까지.

2026-08-31 · David Carrero · password.es
Original: https://password.es/ko/blog/bimilbeonho-api/

---

이 블로그는 몇 달째 같은 말을 반복해 왔다. [비밀번호는 브라우저를 벗어나면 안
된다](/ko/blog/wae-bimilbeonhoreul-eodiedo-bonaeji-anhneunga/).
[생성기](/ko/)는 당신의 기기에서 `crypto.getRandomValues()`로 무작위성을 얻고,
[검사기](/ko/checker/)는 당신이 입력한 것을 어디에도 보내지 않고 분석한다.

그리고 오늘, 서버에서 비밀번호를 만드는 API를 공개한다.

**모순은 명백하고 얼버무릴 생각도 없다.** API의 모든 응답에는 바로 그 말을 담은
경고가 붙어 있다. 하지만 브라우저가 없는 곳이 있다. 계정 백 개를 만드는 스크립트,
임시 자격 증명을 발급하는 서버, 누군가 비밀번호를 요청하면 지어내는 어시스턴트.
그곳에서의 대안은 «브라우저»가 아니다. 잘못 고른 `random()`이거나 손으로 친
문자열이다. 이 API는 그것을 위한 것이다.

## 호출의 전부

키도, 가입도, 헤더도 없다. 이게 전부다.

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

16자 비밀번호와 그 분석이 돌아온다. 이 문단을 쓰는 동안 실행한 결과는
`x*7$9,BUy9PPvOI?`, 89자 알파벳에서 뽑았고 엔트로피 **103.6비트**, 크래킹 시간
2.5 × 10¹¹년. 4단계 중 4단계.

이 숫자들 중 새로운 것은 하나도 없다. 첫 화면의 게이지를 그리는 것과 같은 엔진에서
나온다. [비트](/ko/blog/entropi-biteuran-mueosinga/) 공식도, 공격 모델도 — 초당
10¹² 회 시도, 오프라인, 빠른 해시 — 등급 척도도 검사기와 같다. 같은 비밀번호에
대해 사이트와 API가 다른 숫자를 낸다면 둘 중 하나는 거짓말을 하고 있는 것이다.

## 무엇이 돌아오는가, 필드별로

응답에는 `passwords` — 하나만 요청해도 언제나 배열이다 — 와 `length`, `pool`,
`bits`, `log10_guesses`, `crack_time_log10_seconds`, `crack_time`, `level`,
`level_scale`, `ceiling`이 담긴 `analysis` 블록이 들어 있다.

그중 둘은 한 문단을 받을 만하다. **`level_scale`은 등급이 어디서 나왔는지 말한다**
(오늘은 언제나 `"time"`). 훗날 사이트와 API가 갈라질 때 숫자를 비교해 추론하는
대신 필드에서 바로 보이게 하기 위해서다. 그리고 **`ceiling`은 그 값이 정확한지
상한인지 말한다.** `generate`에서는 늘 `false`다. 비밀번호를 서버가 만들었고 어떤
알파벳을 썼는지 알기 때문이다. 웹 검사기에서는 늘 그럴 수 없다. 그쪽에서는
비밀번호를 당신이 가져오기 때문이다.

이어서 경고인 `notice`, 그리고 플랜, 적용된 언어, 제한, 문서 링크가 담긴 `_meta`
블록이 온다.

## 옵션

모두 선택 사항이고 이름은 영어 그대로다. API를 붙이는 사람은 필드 이름을 그대로
타이핑하기 때문이다. `length`(4–64, 기본 16), `count`(1–20), `lower`, `upper`,
`digits`, `symbols`, `exclude_ambiguous`, `no_repeats`, `lang`.

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

문서에 적혀 있고 연동 전에 알아 두면 좋은 세부 사항 둘. **`exclude_ambiguous`는
일곱 자가 아니라 여섯 자를 뺀다.** `0 O 1 I l | o`를 버리지만 세로 막대는 애초에
기호 집합에 없었다. 그래서 알파벳은 89에서 83으로 내려가고 82가 되지는 않는다.
응답의 `pool`이 83인 이유가 그것이다. 그리고 **`no_repeats`는 절대적인 보장이
아니다.** 웹 생성기와 똑같이 열 번 다시 시도할 뿐이고, 64자에서는 붙어 있는
반복이 약 0.1 % 확률로 빠져나간다. 반대를 약속하는 것보다 이렇게 말하는 편이
쓸모 있다.

## 응답의 언어

기본은 영어다. 아무 말 없이 연동하는 사람이 기대하는 것이 그것이기 때문이다.
URL의 `?lang=`, 본문의 `"lang"`, 헤더 `Accept-Language`로 바꿀 수 있고, 서로
어긋나면 앞의 것이 이긴다. 존재하지 않는 언어는 오류가 아니라 영어로 떨어진다.

여기에는 짐작할 수 없는 비대칭이 있고, 그래서 API가 직접 알려 준다. **메시지는
영어와 스페인어로만 있고, 링크는 사이트의 열여덟 언어 모두에 있다.** 독일어를
요청하면 링크는 독일어, 메시지는 여전히 영어다. 짐작할 필요 없다. `_meta.lang`이
`{ "messages", "links" }`로 각 절반에 무엇이 적용됐는지 알려 준다.

## MCP 서버

MCP는 어시스턴트 — Claude, ChatGPT — 가 외부 도구를 쓰는 프로토콜이다.
`https://api.password.es/mcp`는 가입도 키도 없는 MCP 서버이고, 도구는 하나만
공개한다. 위와 같은 매개변수를 받는 `generate_password`다.

우리에게 가장 중요한 부분이고, 기술 때문이 아니다. **비밀번호를 가져올 데가 없는
어시스턴트는 그것을 지어낸다.** 거기서 나오는 것은 무작위가 아니라 모델이
비밀번호처럼 보인다고 여긴 무언가다. 이 서버를 연결해 두면 즉흥을 그만두고
`crypto.getRandomValues()`로 만든 것을, 분석과 함께, 그리고 도구 설명과 모든
결과에 들어 있는 경고와 함께 돌려준다. 그 경고야말로 어시스턴트가 비밀번호를
요청한 사람에게 결국 읽어 주게 되는 문장이고, 그래서 거기에 있다.

다른 MCP 서버에서 왔다면 한 가지만. **이 서버는 상태가 없다.** POST는 JSON으로
응답하고 스트림을 열지 않으며, `Mcp-Session-Id`는 발급하지도 기대하지도 않는다.
알림에는 본문 없는 202로 답하고 GET은 405를 준다. 2025-06-18 명세가 이를 명시적
으로 허용하지만, 세션과 SSE를 기대하는 사람은 아무도 알려 주지 않으면 깜깜한 채로
디버깅하게 된다.

## 하지 않는 일

**`/v1/check`는 501을 반환한다.** 실수도, 만들다 만 엔드포인트도 아니다. 일부러
그렇게 두었고, 응답 자체가 이유를 설명한다. 검사기와 같은 숫자를 돌려주려면
사이트에서 도는 것과 똑같은 패턴 엔진이 필요하고, 그것은 보내는 내용에 따라 요청당
11 ms에서 3.6초의 CPU를 쓴다. 가입도 키도 없는 서비스에서 이 폭은 제품 결정 —
길이 상한을 어디에 둘 것인가 — 이고 아직 내려지지 않았다. 그때까지 501은 요청한
언어로 사이트의 검사기를 가리키는 `checker_url`을 담아 준다. 그쪽은 아무것도 보내지
않고 바로 그 일을 한다.

계정도, 키도, 요금제도 없다. 존재하지 않으니 API 어디에도 가입 링크가 단 하나도
없다. 모두가 반드시 넣는 «제한 초과» 오류 안에조차 없다.

## 제한

하나, 그리고 실제로 적용되는 것도 그것이다. **IP당 분당 60회 요청.** 이 페이지를
믿을 필요는 없다. 그 숫자는 모든 응답 안의 `_meta.limits.burst`에 실려 온다.
넘기면 `Retry-After`와 `RateLimit-*` 헤더가 붙은 429가 나온다.

`_meta`에는 값이 `null`인 `quota` 블록도 보인다. 계정이 생길 때를 위해 예약해 둔
자리이고, 일부러 비워 두었다. **공지만 하고 강제하지 않는 제한은 아예 공지하지
않는 것보다 나쁘다.** 연동하는 쪽은 그것을 지키며, 아무도 세지 않는 숫자를 향해
코드를 짜게 되기 때문이다.

## 그래도 두 번 생각하길

비밀번호를 생성하는 API는 근본적으로 안티패턴이다. 비밀번호가 네트워크를 지나
당신 것이 아닌 기계를 거친다. 우리가 아무것도 저장하지 않는다는 사실은 문제의
모양을 바꾸지 않고 우리 몫만 바꿀 뿐이다. 그리고 [확인할 수 없는 약속이 얼마나
값어치가 있는지](/ko/blog/wae-bimilbeonhoreul-eodiedo-bonaeji-anhneunga/)는 이미
알고 있을 것이다.

그래서 경고는 이 페이지에만 있지 않다. 요청한 언어로, 모든 응답에 실려 다닌다.
그리고 그래서 이 문단은 문서 맨 끝에 숨겨 두지 않고 여기에 있다. **당신이 직접 쓸
비밀번호라면, 이 사이트의 [생성기](/ko/)는 전부 브라우저 안에서 돌고 아무것도
보내지 않는다.** API는 다른 쪽을 위한 것이다. 화면 앞에 아무도 없을 때 일어나는
일을 위한 것.

자세한 내용은 두 페이지에 있다. [API가 무엇인가](/ko/api/)는 누구를 위한 것인지,
오늘 무엇이 응답하고 무엇이 응답하지 않는지 알려 준다. [레퍼런스](/ko/api/docs/)에는
아홉 개의 매개변수, 모든 필드의 항목별 설명, 오류 코드, 제한이 있다. 에디터 옆에
띄워 두는 쪽이 이것이다. 그리고 기계가 읽기를 원한다면 `openapi.json`이 있다.

---

*출처: API 자체, 2026년 8월 31일 프로덕션 대상 검증 — `POST /v1/generate`,
`POST /v1/check`(501), `POST /mcp`, `GET /openapi.json` · 분석 수치는
password.es의 생성기 및 검사기와 같은 엔진에서 나온다 · 공격 모델은 초당 10¹² 회
시도, 오프라인, 빠른 해시로 사이트의 나머지와 같다 · MCP 서버는 2025-06-18 명세를
상태 없는 Streamable HTTP 전송으로 구현한다.*
