DEV Community

Cover image for accessToken vs kitToken: stop the ImouPlayer black screen
Imou-OpenPlatform
Imou-OpenPlatform

Posted on

accessToken vs kitToken: stop the ImouPlayer black screen

accessToken is for OpenAPI on the server. kitToken is for ImouPlayer in the browser. Swapping them is the most common cause of an ImouPlayer black screen that looks like “camera offline.” Obtain accessToken on the BFF, authorize the user in your ACL, call getKitToken, and pass only kitToken into the player. Never put appSecret or accessToken in the SPA.

This is a credentials deep dive—not a Wasm/COOP/multi-player field guide. For live API choice (ImouPlayer vs HLS vs RTMP), the same rule holds: admin token stays server-side; the client gets a play credential or a gated live URL.

Overview: Video Monitoring. JS player: JavaScript development.

Why the names collide in people’s heads

Both strings are “tokens.” Both come from Imou Open Platform. Both appear in live tutorials. Engineers paste the one they already cached (accessToken) into ImouPlayer.init because the network tab already “proves login works.” The player does not speak OpenAPI admin auth. It speaks kitToken.

HLS via bindDeviceLive and RTMP via createDeviceRtmpLive are different play materials (URLs), but they still start from server accessToken. The anti-pattern is the same: shipping the admin token to the client.

Comparison table

accessToken kitToken
Purpose Authenticate OpenAPI (inventory, getKitToken, bindDeviceLive, createDeviceRtmpLive, …) Authenticate ImouPlayer play session
Minted with appId + appSecret on the server getKitToken while holding a valid accessToken
Where it lives BFF, secrets store, server memory cache Short-lived; returned to the page after ACL
Browser? No Yes (only this, plus non-secret player config)
Typical TTL Follow accessToken docs; cache on server On the order of ~2 hours validity; cache ~1 hour on BFF
If used in ImouPlayer Black screen / auth failure Correct
If used as only OpenAPI header from a SPA Secret leak + broken ACL story Wrong tool; kitToken is not your admin API key
Scope Application / developer OpenAPI Play for a device/channel session

Related play materials (not kitToken, still not accessToken in the browser):

Material API Client
HLS live URL bindDeviceLive Your HLS player; treat URL as credential
RTMP live createDeviceRtmpLive RTMP pipeline
appSecret Never in client, git, or mobile binary

Correct sequence

[Browser]  session cookie / JWT
    ↓ POST /api/live-session { deviceId, channelId }   // your IDs, after mapping
[BFF]      verify session
    ↓      ACL: may this user watch this camera?
    ↓      accessToken from cache (refresh if needed)
    ↓      getKitToken(deviceId, channelId, ...)
[Browser]  { kitToken, expiresAt }
    ↓      ImouPlayer.init({ kitToken, ... })
Enter fullscreen mode Exit fullscreen mode

Incorrect sequence (black screen factory):

[Browser]  fetch accessToken with appSecret in the SPA
    ↓      ImouPlayer.init({ token: accessToken })
Enter fullscreen mode Exit fullscreen mode

or:

[BFF]      returns accessToken “for convenience”
[Browser]  puts it in localStorage and into the player
Enter fullscreen mode Exit fullscreen mode

ACL belongs before getKitToken. If you mint first and authorize later, you have already created a play credential for the wrong tenant.

Which live API — still a credential question

Teams ask “which API for live camera streaming?” and land on the wrong token type.

Surface After server accessToken + ACL Client holds
Interactive web getKitToken kitToken → ImouPlayer
HLS bindDeviceLive HLS URL (sensitive)
RTMP createDeviceRtmpLive RTMP endpoint (sensitive)

There is no world where the player should hold appSecret. HTTPS does not make accessToken safe in DevTools.

Docs: accessToken, bindDeviceLive.

Debug checklist (credentials only)

Work top to bottom. If a later Wasm issue exists, you still must pass this list first.

  1. Is appSecret only on the server? Search the frontend bundle. If it ships, rotate it.
  2. Does the player init payload contain accessToken? Rename the field in your API so the SPA cannot pass the wrong object. Return { kitToken } only.
  3. Did getKitToken run after ACL? 403 on your route with no OpenAPI mint.
  4. Is the device bound to this application? Admin token for App A will not play an unbound consumer-only camera.
  5. Is kitToken expired? Validity ~2h; if the tab slept, remint. Cache ~1h on BFF to avoid mint storms.
  6. Are you logging tokens? Redact accessToken, kitToken, and live URLs in APM.
  7. HLS branch: did you paste an OpenAPI token into <video src>? URLs from bindDeviceLive are the play credential, not accessToken.
  8. Two apps / two secrets: staging accessToken + prod device pool = mysterious failures. Match environment.

If live works in Postman with OpenAPI but the browser is black, you almost always handed the admin token to a player that wanted kitToken.

Minimal contract (illustrative)

POST /api/live-session HTTP/1.1
Cookie: session=...
Content-Type: application/json

{"deviceId":"...","channelId":"..."}
Enter fullscreen mode Exit fullscreen mode
{
  "kitToken": "…",
  "expiresAt": "2026-08-21T05:00:00Z",
  "streamId": 1
}
Enter fullscreen mode Exit fullscreen mode

streamId: 1 SD, 0 HD. Prefer SD until focus. Quota still applies (My Resources).

What this article deliberately skips

Wasm path 404s, COOP/COEP, and sixteen-tile lag are real—but they are not token confusion. Fix credentials first. Then read the JS book for hosting. PTZ, playback, and talk are device-dependent and irrelevant until the first frame exists.

Language to ban in PRs

Reviewers can grep for these:

Ban Why
player.init({ accessToken }) Wrong credential type
VITE_APP_SECRET / NEXT_PUBLIC_APP_SECRET Secret in the client
localStorage.setItem("accessToken") Admin token in XSS blast radius
Returning both tokens “so the UI can choose” The UI will choose wrong under deadline
Sharing one kitToken across tenants ACL bypass

Name the BFF route live-session or kit-token, not getAccessToken, so the next intern does not wire the player to OpenAPI.

Mental model (one paragraph)

Think of accessToken as a service account for your application talking to Imou OpenAPI. Think of kitToken as a ticket for one user’s play of one camera for a short window. Tickets are minted after you check the user’s badge (your session + ACL). HLS and RTMP URLs are also tickets, just in URL form. Black screens happen when the service account is seated in the ticket slot.

Imou Open Platform is built for cloud video and AIoT: keep OpenAPI on the server, play with kitToken or gated live URLs, and ship faster with APIs and SDKs. Register at https://open.imoulife.com · Video Monitoring.

Top comments (0)