Self-hosted service
Phineas/lanyard avatar
Phineas/lanyard

Lanyard: Discord Presence API, WebSocket Feed, and KV Store

🏷️   Expose your Discord presence and activities to a RESTful API and WebSocket in less than 10 seconds

1,485 stars197 forksElixirMIT

At a glance

What is it?
Lanyard exports live Discord presence and activity data through REST and WebSocket interfaces, with a hosted service available immediately and Docker support for self-hosting. It suits websites that need current Discord status without implementing Discord RPC directly.
Who is it for?
Adopt Lanyard when a website or application needs a simple HTTP or WebSocket view of Discord presence and the hosted service meets your privacy and availability requirements. Do not adopt it if your application needs its own private transport, custom Discord RPC handling, or deployment controls that the README does not describe.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Elixir, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why Lanyard Sits Between Discord and Your Website

Lanyard solves a narrow integration problem: an application wants current Discord presence data without building and maintaining its own connection to Discord RPC. The target user is typically a developer displaying presence on a personal website, profile, stream overlay, dashboard, or other application. The README gives Spotify on a personal website as its motivating example.

Discord presence includes more than an online or offline marker. The documented response can report `active_on_discord_mobile`, `active_on_discord_desktop`, `listening_to_spotify`, the current Discord status, user information, and an `activities` array containing the activity data sent with the presence. When Spotify is active, Lanyard also supplies a derived `spotify` object containing the track, artist, album, timestamps, and album art URL. That makes the service useful to presentation software that knows how to read JSON but does not implement Discord's presence protocol.

Lanyard also has a separate KV capability. This can be updated through the Lanyard Discord bot or API, and the resulting key-value data appears under the `kv` field in a user's presence response. The README describes it as a globally accessible real-time KV store. Its examples include storing a location, but it should not be confused with a general-purpose database because the README does not document durability, consistency guarantees, retention, or availability guarantees.

The fastest intended path requires no local installation. Joining the project's Discord server causes presence to begin appearing through the hosted endpoint. That convenience also creates the main adoption boundary: a hosted intermediary participates in the data path. Projects with strict data handling, networking, or operational requirements should examine that architecture before relying on it.

REST Requests and the Presence Response Shape

The REST interface follows a conventional resource path. To retrieve one user's presence, send a `GET` request to `https://api.lanyard.rest/v1/users/:user_id`, replacing `:user_id` with the Discord user ID whose presence should be read. The response is wrapped in a top-level `success` field and a `data` object.

Presence is not identical to a simple status string. A consumer must account for the separate mobile and desktop activity flags, the textual `discord_status`, and the activities array, which can be empty or contain different activity types. Spotify has an additional convenience object, but the README states that this object is `null` when `listening_to_spotify` is false. Code should therefore use the presence data defensively rather than assuming that every optional field exists or that Spotify is active.

The included example also embeds KV data in the same response. This makes a polling client simpler because it can retrieve presence and attached KV state through one request. It does not make Lanyard a general API gateway: the documented path is specifically for a user's presence, and the README excerpt does not describe arbitrary route composition.

For applications that need changes rather than periodic requests, the README provides WebSocket subscriptions for one user, multiple users, or every user presence. Subscription opcodes, events, and error codes are listed in the README's table of contents, but the displayed API section does not include their complete payloads. An implementation should therefore use the linked API documentation rather than infer message formats from the REST response.

React Setup Through the use-lanyard Hook

For React applications, the README identifies `use-lanyard` as its recommended library. The hook subscribes over the WebSocket, so a page can receive live presence updates rather than repeatedly polling the REST endpoint. Multiple hooks in an application share one connection, which avoids creating a separate connection for each component that displays a presence.

The repository's example requires the dependency and a Discord user ID. The `YOUR_DISCORD_ID` token in the example is a placeholder, not a literal identifier. Install the library using the package manager for the surrounding application, then replace that token with the intended Discord ID. The README does not include the dependency installation command, so this article does not invent a version or package-manager invocation.

The hook initially returns `undefined`. A component must render a fallback while waiting for the first presence event instead of immediately dereferencing `discord_user`. The documented example does this by accessing the username only after optional chaining has established that the returned presence exists. An empty Discord ID should not be treated as a valid subscription target, although the README does not specify the library's validation behavior for that case.

The same hook can receive an array of IDs when one interface needs several user presences. This is useful for a community page or comparison view, but the displayed README section does not state the maximum subscription count. It also does not describe reconnect behavior, error rendering, stale-event handling, or server event names in enough detail to reproduce the WebSocket client independently.

Hosted Setup and Your First Presence Request

The shortest first use is through the hosted service. The README instructs users to join the Lanyard Discord server, after which the service receives the Discord presence needed to populate the user's API record. No repository checkout, Elixir installation, or local process is required for this path.

Once the account's presence has appeared, identify the relevant Discord user ID and request its record. The endpoint syntax is:

http
GET https://api.lanyard.rest/v1/users/:user_id

Replace `:user_id` with the numeric Discord user ID before making the request. A successful response contains `success: true` and a `data` object. The exact fields depend on the current Discord state, so compare the output with the documented shape rather than assuming `spotify` or meaningful `activities` will always be present.

The README does not document authentication for presence reads. It does document obtaining an API key for KV access, which indicates that read-only presence retrieval and authenticated KV mutation are separate concerns. Anyone building an application should avoid placing a KV API key in browser source code or public environment variables, although the displayed API section does not define the credential delivery rules for client applications.

For the example use case of displaying what someone is listening to, the first check is whether `listening_to_spotify` is true. Only then should the application read the derived Spotify fields. This check matters because the README explicitly says the `spotify` object is `null` outside Spotify listening.

Docker Self-Hosting and Its Configuration Gap

Self-hosting requires more work than using the hosted API. The repository includes a `Dockerfile` with an Elixir build image and a smaller runtime image based on the same Alpine distribution. The build stage installs Git, downloads Hex and Rebar dependencies, fetches Elixir dependencies, compiles the application, and creates a release. The runtime stage installs `ca-certificates` and `redis`, copies the release to `/opt/lanyard`, and starts it with `/opt/lanyard/bin/lanyard start`.

The image definition states these commands directly:

dockerfile
CMD [ "/opt/lanyard/bin/lanyard", "start" ]

This confirms that the compiled release is the container entry point. The presence of Redis in the runtime image also shows a service dependency in the image, but the `Dockerfile` does not explain Redis configuration or whether an external Redis deployment is required. The top-level repository contains `config/`, which suggests application configuration exists, but the displayed file list does not include the relevant settings. Consequently, a copy-paste deployment cannot be derived from the `Dockerfile` alone without consulting the repository's configuration documentation.

The README explicitly says self-hosting requires configuration, but it does not identify required environment variables, secret names, ports, or network settings. It also does not give a `docker build` or `docker run` invocation. Inventing those details would turn an incomplete deployment tutorial into a likely failure. Self-hosting should therefore be treated as an operator task involving the Elixir release configuration and Redis, not as a zero-configuration container.

KV Access, Licensing, and Maintenance Boundaries

The KV feature broadens Lanyard beyond passive presence distribution. According to the README, a key-value pair can be set and deleted, updates can originate from the Lanyard bot or API, and an API key is required for KV operations. The documentation also has a dedicated limits section, but its values do not appear in the displayed API section. Applications must read those limits before selecting keys, value sizes, write frequency, or retention assumptions.

REST reads, WebSocket subscriptions, and authenticated KV writes have different integration costs. Presence display requires little local infrastructure when using the hosted endpoint. WebSocket consumers still need connection lifecycle handling and UI states for the period before the first event. KV clients add credential management and must respect the documented write and delete operations. Self-hosting adds release configuration and Redis coordination, although the README does not specify the precise operator workload.

Lanyard is released under the MIT license. That permits use and modification under the license's conditions, but this review does not interpret those conditions as legal advice. The repository is not archived, and its last push was on 2026-08-15. There are no GitHub releases, so there is no published release history here from which to infer a stable upgrade cadence or compatibility policy. Operators should treat changes in `mix.exs`, `mix.lock`, `config/`, and `Dockerfile` as the concrete files to review before an upgrade.

Editorial conclusion

Adopt Lanyard when a website or application needs a simple HTTP or WebSocket view of Discord presence and the hosted service meets your privacy and availability requirements. Do not adopt it if your application needs its own private transport, custom Discord RPC handling, or deployment controls that the README does not describe. Before committing, verify the available REST and WebSocket endpoints, the KV update requirements, the documented limits, and whether self-hosting needs additional configuration beyond the repository's `Dockerfile`.

Frequently asked questions

How do I publish my Discord presence with Lanyard?

Join the Lanyard Discord server, then request `GET https://api.lanyard.rest/v1/users/:user_id` with your numeric Discord user ID. The README says your presence will begin appearing after joining.

Can Lanyard update a React website in real time?

The README recommends `use-lanyard`, which subscribes over the WebSocket. Multiple hooks share one connection, and the hook returns `undefined` until the first presence arrives.

Can I self-host Lanyard with Docker?

The repository includes a `Dockerfile` that builds an Elixir release and includes Redis in the runtime image. The README says configuration is required, but it does not document the required settings or provide `docker build` and `docker run` commands.

Does Lanyard include something beyond Discord presence?

Yes. Lanyard documents a real-time KV store that can be updated through its Discord bot or API. KV operations require an API key and are subject to limits documented separately in the README.

Official sources

  1. Issues
  2. License: MIT
  3. Phineas/lanyard on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/phineas-lanyard.svg)](https://hysenlabs.com/projects/phineas-lanyard)

Was this useful?