OpenKakao

Authentication

How OpenKakao authenticates, how recovery policy works, and where unattended assumptions stop.

Authentication

OpenKakao derives authentication material from the running KakaoTalk macOS app and stores reusable credentials locally only when you ask it to.

Token classes

Credential pathSourceBest for
saved credentials~/.config/openkakao/credentials.jsonnormal CLI startup
Cache.db extractionrecent KakaoTalk macOS request statefallback when saved state is stale
login.json reloginreconstructed desktop login flowrestoring LOCO-facing commands
refresh_token renewalrenewal endpoints + cached refresh tokensupervised token refresh attempts
auth.password_cmdexternal secret command such as Dopplerunattended relogin without storing a plaintext password locally

Transport boundary

  • REST: profile, friends, settings, recently opened chats, cached messages
  • LOCO: full chat list, full message history, send, watch, media flows

If you care about stable automation, use REST for cheap health checks and LOCO for real chat work. The fuller boundary is documented in REST vs LOCO.

Initial login

openkakao-rs login --save

That command extracts the local inputs it needs, performs login, and writes credentials to:

~/.config/openkakao/credentials.json

The file is created with 0600 permissions.

Health checks

openkakao-rs auth
openkakao-rs doctor
openkakao-rs auth-status

Use auth for a fast REST-side check. Use doctor --loco when you need to know whether the stricter LOCO path is healthy too. Use auth-status when you want the persisted recovery and cooldown state directly.

Recovery policy

openkakao-rs relogin --fresh-xvc
openkakao-rs renew

The recovery ladder is now policy-driven:

  1. reuse saved credentials
  2. try relogin or renew first depending on config
  3. try the remaining recovery path if enabled
  4. fall back to fresh Cache.db extraction

Default behavior remains conservative:

  • auth.prefer_relogin = true
  • auth.auto_renew = true

That means the default credential loading order is:

  1. Saved credentials (~/.config/openkakao/credentials.json) -- fastest path, no network call. The CLI checks this first on every invocation.
  2. login.json relogin -- reconstructs the desktop login flow with X-VC header to get a fresh access_token (~65 chars). Works for both LOCO and REST.
  3. refresh_token renewal -- uses the cached refresh_token to request a new access_token from renewal endpoints. Lighter than full relogin but depends on the refresh_token still being valid.
  4. Fresh Cache.db extraction -- extracts the bearer token from the KakaoTalk macOS app's HTTP cache. This token (~138 chars) only works for REST, not LOCO. This is the last resort.

If you disable auto_renew, the refresh_token renewal step is skipped entirely. If you set prefer_relogin = false, the CLI attempts refresh_token renewal before login.json relogin. If you set auth.password_cmd, relogin can source the password from an external command such as Doppler instead of relying only on cached request state.

Do not build unattended jobs that assume recovery will always succeed after upstream client or server changes.

The recovery context now persists in:

~/.config/openkakao/state.json

That lets watch, LOCO commands, and REST commands share cooldown history across process restarts.

Unattended mode

Commands that can create side effects without a human in the loop require an explicit global opt-in:

  • send -y
  • send-file -y
  • send-photo -y
  • watch --read-receipt
  • watch --hook-cmd
  • watch --webhook-url

Example:

openkakao-rs --unattended --allow-watch-side-effects watch --hook-cmd 'jq . > /tmp/event.json'

The point is simple: if the CLI is going to act without waiting for you, you should have to say that plainly.

For persistent setups, move those permissions and auth policy into Configuration.

Failure patterns

CodeMeaningTypical response
-950token expired or LOCO login rejectedrun relogin, then verify whether renewal should still be enabled
-300device or request mismatchinspect identifiers, local app state, and login inputs
-203missing required parameter (incomplete request body)re-run login --save and verify extracted fields
-400missing parametersre-run login and validate extracted inputs

Next

On this page