Social — entry 016 of 39

Lanyard

Verified Jul 2026

Lanyard exposes a Discord user's live presence — online status, current activities (games, Spotify listening data), and any custom key-value data set via their Discord bio — over a free public REST endpoint or a subscribable WebSocket feed, with no authentication required. The catch is that both the requester and the target user must share a Discord server with Lanyard's bot, since Discord's gateway only surfaces presence data for mutual-guild members.

Lanyard exposes a single read route, `/users/{discord_id}`, that mirrors a Discord user's live presence -- online status, current activities (games, Spotify listening data), and a self-set `kv` bio map -- with no authentication at all. A live GET this run against Lanyard's own author's Discord id, `94490510688792576`, returned genuine live presence JSON.

discordpresencewebsocketreal-timestatus
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSEnabledCallable directly from browser JavaScript.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score74out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs0/20No docs or spec available
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 74 on greatapis.com
<a href="https://greatapis.com/api/lanyard/"><img src="https://greatapis.com/badge/lanyard.svg" alt="Scored 74 on greatapis.com"></a>

Auth quickstart

  1. No API key, signup, or credit card required -- a live GET this run returned real presence data with zero credentials. The actual gate isn't auth: the target Discord user must have joined Lanyard's own Discord server so its bot can observe their presence (see gotchas); no key exists that lifts this requirement.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

Fetch a monitored user's live presence

GEThttps://api.lanyard.rest/v1/users/94490510688792576

200 application/json; charset=utf-8

{"data":{"discord_user":{"id":"94490510688792576","username":"phin","global_name":"Phineas"},"...":"discord_status, activities, kv omitted -- all volatile, change minute to minute"},"success":true}

`94490510688792576` is Lanyard creator Phineas's own Discord id, used here because he necessarily shares a guild with his own bot. `discord_status`, `activities`, and `kv` are elided above because they change from one request to the next -- only `success` and `discord_user.id` are safe to treat as fixed points.

Try it

Developer reference

Base URLhttps://api.lanyard.rest/v1
Key endpoints
  • GET/users/{discord_id}

Gotchas & limits

  • A Discord id the bot doesn't see returns **HTTP 404** `{"error":{"code":"user_not_monitored","message":"User is not being monitored by Lanyard"},"success":false}` -- a live GET this run against `/users/1` confirmed it. "Keyless" does not mean "works for any Discord user": the target must have joined Lanyard's own Discord server first, and there is no key or parameter that lifts this.
  • `/users/{id}/kv/{key}` is write-only and needs the user's own Lanyard API key to `PUT`/`DELETE` a value -- a bare live GET this run against it returned `HTTP 404` `{"error":{"code":"not_found","message":"Route does not exist"},"success":false}`, not the key's value or a permissions error. This quickstart's only hero endpoint is the read route above; the write-only kv route is documented but out of scope here.
  • `activities`, `discord_status`, and the user-set `kv` map change minute to minute as the target's Discord client and Spotify state change -- do not treat any value under them as a fixed fact; this seed elides them for exactly that reason.
  • The only other Lanyard surface is a subscribable WebSocket gateway (`wss://api.lanyard.rest/socket`) for push updates instead of polling this REST route -- out of scope for a keyless REST quickstart, but worth knowing before building a polling loop against this route instead.