LeetCode Stats Card: a live stats image for your README
Show your dynamically generated LeetCode stats on your GitHub profile or your website!
At a glance
- What is it?
- LeetCode Stats Card renders your LeetCode problem solving stats as an SVG card served from a Cloudflare Worker, and you embed it in a README with a single image line. The options are extensive, the cache is controllable, and the whole service can be self hosted from the published Docker image when you would rather not send traffic to somebody else's endpoint.
- Who is it for?
- Adopt LeetCode Stats Card if you want a live LeetCode stats image in a README and do not mind depending on an upstream site that can change its pages at any time. Do not adopt it as a dashboard for anything that matters, since the numbers come from a third party site you do not control.
- 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 TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A card rendered by a Worker, not an image you maintain
LeetCode Stats Card shows dynamically generated LeetCode stats on your GitHub profile or your website. Both the LeetCode and LeetCode CN sites are supported, and the card is served from an endpoint rather than being a file you commit.
The mechanism is an HTTP image. The service renders an SVG card and returns it, and your README embeds that URL. The browser and GitHub both fetch it, so the numbers on your profile update without you regenerating anything. The README calls out a fast and global edge network based on Cloudflare Workers, and the repository contains a wrangler.toml, which is the Workers configuration file.
That architecture explains the feature list. Themes and fonts are cheap to vary because the card is rendered per request. Custom stylesheets work because the response is generated rather than stored. The cache is controllable because the service decides how long a rendered card lives before it refetches the data, with a default of 60 seconds and the option to set it to zero.
The audience is a developer who wants a profile card. It is a small, self contained service with an MIT licence, an npm package named leetcode-card, and a core package inside the monorepo at packages/core/src/index.ts that the README describes as a highly extensible system.
The alternative approach to the same result is to generate the card locally in a scheduled job and commit the resulting SVG into your repository. That gives you a static artefact and no dependency on a third party service, at the cost of a workflow and of numbers that are only as fresh as your last run.
Embedding the card takes one line
The usage section is deliberately minimal. You copy the line into your README.md and change the path to your LeetCode username, which is case-insensitive:
If you want the card to link somewhere, the markdown becomes a linked image:
[](https://leetcode.com/JacobLinCool)The endpoint is leetcard.jacoblin.cool, and the README also lists a legacy endpoint at leetcode.card.workers.dev for older setups.
There is a playground at leetcard.jacoblin.cool where you can try the options before putting anything in a profile. That is worth using first, because the option set is large enough that the rendered result is easier to judge visually than to derive from the documentation.
One thing to know is how the card ages in a repository. GitHub fetches and caches the image, which is the reason the README warns against setting a long cache time: a long value means the card you see may be an old rendering for reasons that have nothing to do with your settings.
Query options are a URL, which is the whole configuration surface
Every option is a query string parameter, and the default values are documented. `site` selects the data source and can be `us` or `cn`, defaulting to `us`. `theme` picks the card theme, defaulting to light,dark, and a comma separates the light and dark variants.
`colors` overrides the theme palette with your own comma-separated hex colors, in the format bg0,bg1,text0,text1,color0,color1,color2,color3. You may provide fewer values and the missing ones are padded by repeating the last one you gave. When both theme and colors are provided, colors takes precedence, which is the detail to remember if a theme setting seems to have no effect.
`font` selects the font and you can use almost all fonts on Google Fonts. It is case-insensitive, so font=dancing_script and font=Dancing%20Script give the same result.
`width` and `height` default to 500 and 200 and change the card size without resizing the content, which the README says is helpful if you are writing custom CSS rather than a way to fit more in. `border` and `radius` default to 1 and 4. `animation` defaults to true and can be turned off with animation=false. `hide` takes a comma-separated list of element ids, such as ranking, total-solved-text, easy-solved-count, medium-solved-count and hard-solved-count, which is how you strip parts of the card you do not want.
`sheets` takes a comma-separated list of URLs for external stylesheets, injected in the order you list them, and the README suggests uploading your CSS to a gist and passing the URL.
Extensions add cards, but only one at a time
The `ext` parameter selects extended cards, and there are three of them: activity, contest and heatmap. The README states the constraint plainly, that you can only use one of the extended card extensions at a time, with the possibility that they could be combined in the future.
That is a real limitation and it is a design decision rather than an oversight. The extension system is how features are added: the README notes that animation, font, theme and the external stylesheet are all implemented by extensions and enabled by default, and it invites pull requests for a new extension, using nyan-cat as the example of what a contribution might look like.
So the extension list is not a fixed set of three add ons. It is the extension point of the system, with three extensions currently shipped. The monorepo layout supports that reading, with packages/ holding the pieces and a core package that the README calls highly extensible.
For a user, the practical consequence is that the extension list can grow between releases without a version bump, and that a custom extension is a real way to make the card your own rather than only restyling it.
Cache control, including a delete endpoint
The `cache` parameter is the cache time in seconds, defaulting to 60. The README gives the reason not to set it long, that GitHub will fetch and cache the card.
The behaviour is worth thinking through, because there are two caches in play and the parameter only controls one of them. The service caches its own rendered card for the given number of seconds, which protects the upstream LeetCode site from a request per profile view. GitHub then caches the image it fetched, and that second cache is not under your control. A short service cache keeps the numbers accurate; it does not force GitHub to refetch.
Setting cache=0 disables the service side cache, which the README shows as an option and which is the right setting when you are debugging a change and need to see fresh data on every request.
There is also a documented escape hatch for a stale card. You can make a DELETE request to /:site/:username to delete the cache. That is a useful thing to know about, because it means you can force a refresh without waiting out a cache window, and it is documented rather than hidden.
The no tracking claim sits alongside this in the feature list, and the caching mechanism is consistent with it: the service stores a rendered card keyed by user, and the README does not describe any analytics on top of that.
Self hosting the worker, and the Docker path
The README documents self hosting through the jacoblincool/leetcode-stats-card Docker image, and the repository has the pieces to run it.
The compose file in the repository root is short and shows the shape of a self hosted instance:
version: "3.8"
services:
worker:
build: .
image: jacoblincool/leetcode-stats-card
volumes:
- ./.storage/cache:/worker/cache
ports:
- "8080:8080"A cache directory mounted from the host, and the service published on port 8080. The Dockerfile is built on the workerd runtime:
FROM jacoblincool/workerd:latest
COPY ./worker.capnp ./worker.capnp
CMD ["serve", "--experimental", "--binary", "worker.capnp"]The root package.json shows how the image is produced, with the build:image script compiling the worker bundle and then running docker compose build. The same file shows a pnpm workspace with separate build scripts for the worker and for the npm package, a test script running vitest with coverage over packages/*/src, eslint for linting, prettier for formatting and husky for git hooks.
Self hosting is therefore a real option rather than a note in the docs, and it is the way to use the card if you would rather not have your LeetCode username and profile picture travel to a third party endpoint on every README render.
Where the card stops: it reads a site you do not control
The limitation is inherent to the approach and worth stating before anyone embeds one.
The stats come from LeetCode, so the card depends on a site you do not control. It can break without anything changing in the repository, and the failure mode is a broken image in a README rather than an error message anyone will chase.
The same applies to the privacy story. The card displays a user's LeetCode profile picture and solving statistics, so a public endpoint necessarily sees which usernames are being requested. The no tracking claim covers the card service's own analytics, and the option to self host removes the third party endpoint from the path entirely.
On the project itself, the licence is MIT and the work is a monorepo with packages/ for the core, the Cloudflare worker and the npm package. The root package.json reports version 1.0.1. The repository publishes no GitHub releases, the last push was on 2026-10-15, and the npm package is leetcode-card.
The honest summary is that this is a small, well documented, self hostable service for a decorative purpose, and the decorations are the right size for the risk. Use it on a profile, pin it in a project README, and keep it away from anything that has to be correct.
Editorial conclusion
Adopt LeetCode Stats Card if you want a live LeetCode stats image in a README and do not mind depending on an upstream site that can change its pages at any time. Do not adopt it as a dashboard for anything that matters, since the numbers come from a third party site you do not control. Before you embed it, decide whether the public endpoint or your own self hosted instance is acceptable, keep the cache setting short, and note the licence is MIT with the last push on 2026-10-15 and no GitHub releases.
Frequently asked questions
How do I put the LeetCode Stats Card on my GitHub profile?
Copy the image markdown into your README.md and replace the path with your LeetCode username, which is case-insensitive: .
Can I self host the LeetCode Stats Card?
Yes. The README points to the jacoblincool/leetcode-stats-card Docker image, and the repository includes a docker-compose.yml that mounts a cache directory and publishes the worker on port 8080, with the image built using the pnpm build:image script.
How do I change the colors and font of the card?
The colors parameter takes up to eight comma-separated hex values in the order bg0,bg1,text0,text1,color0,color1,color2,color3 and takes precedence over theme, while the font parameter accepts almost any Google Font name and is case-insensitive.
Can I show the activity, contest and heatmap cards at the same time?
Not at the moment. The README states that only one of the extended card extensions, activity, contest or heatmap, can be used at a time, though they may be combined in the future.
How do I force the card to refresh when it looks stale?
The cache parameter controls the server side cache time in seconds, with 60 as the default, and you can make a DELETE request to /:site/:username to delete the cached card. The README also warns that GitHub caches the image it fetches, so a long cache time is not a good idea.
Official sources
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.
[](https://hysenlabs.com/projects/jacoblincool-leetcode-stats-card)Was this useful?