DEV Community

Colin
Colin

Posted on

GitHub Readme Stats Not Working? How to Fix 503, Rate Limits, 403 and Broken Images

You open your GitHub profile and the stats card is gone. All that's left is a broken image icon, or a grey "Something went wrong" box. Nothing changed in your README, so what broke?

Almost always, the problem is the public service that draws the card, not your Markdown. Below is how I narrow it down, and three fixes that actually last.

Last verified: Oct 14, 2026.

TL;DR

Symptom Likely cause Fastest fix
503 / DEPLOYMENT_PAUSED Public github-readme-stats instance paused GitHub Actions or self-host
"Something went wrong" card GitHub API rate limit or a fetch error Your own token (Actions / self-host)
403 Forbidden on streak card Public streak endpoint blocking requests Streak Stats GitHub Action
Broken image icon, no error Slow response or a cached failure behind GitHub's image proxy Static SVG in your repo
Card shows the wrong data Typo, wrong username, cache Check the URL and wait out the cache

Step 1: Is it you or the service?

Copy the image URL out of your README and open it straight in your browser. Or check the headers:

curl -I "https://github-readme-stats.vercel.app/api?username=YOUR_USERNAME"
curl -I "https://streak-stats.demolab.com/?user=YOUR_USERNAME"
Enter fullscreen mode Exit fullscreen mode
  • 200 with image/svg+xml and a normal card: the service is fine. The problem is in your README (see Step 6) or a stale cached copy on GitHub.
  • 200 but the SVG says "Something went wrong": the service is up but couldn't fetch your data. This is usually a rate limit.
  • 503: the instance itself is down or paused.
  • 403: the endpoint is refusing the request.

When I checked on Oct 14, both public endpoints returned 200. They work most days, but they go down every so often, so "it works right now" doesn't mean it'll still work tomorrow.

Step 2: Know why the public instances break

503 DEPLOYMENT_PAUSED. In #3851 ("Public deployment paused"), the maintainers explain that Vercel's sponsorship ended. They point people to GitHub Actions or self-hosting instead. #4737 and #4798 ("not working again ?") are both still open. The repo README now also says the project is no longer maintained and recommends its successor, GitHub Stats Extended.

Rate limits. The README says the public instance is "best-effort and can be unreliable due to rate limits and traffic spikes." Thousands of profiles share one pool of GitHub API requests. When that pool runs out, you get the error card.

403 on Streak Stats. In streak #872, users reported every public streak endpoint returning 403. That issue is closed now, but it can happen again.

Broken image, no error. GitHub doesn't load README images straight from the source. It serves them through its own image proxy (camo). If the card service is slow, the image may just not appear. Users have reported this in streak #754 and #792.

Step 3 (recommended): Generate the SVGs with GitHub Actions

This is the fix that holds up best. A workflow builds the cards on a schedule and commits them to your profile repo. Your README then points at a file in your own repo, with no outside service in the way.

Stats and top languages card. Save this as .github/workflows/grs.yml in your USERNAME/USERNAME repo. It's adapted from the action's README:

name: Update README cards
on:
  schedule:
    - cron: "0 0 * * *"
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v6
      - uses: stats-organization/github-readme-stats-action@v2
        with:
          card: stats
          options: username=${{ github.repository_owner }}&show_icons=true
          path: profile/stats.svg
          token: ${{ secrets.GITHUB_TOKEN }}
      - uses: stats-organization/github-readme-stats-action@v2
        with:
          card: top-langs
          options: username=${{ github.repository_owner }}&layout=compact
          path: profile/top-langs.svg
          token: ${{ secrets.GITHUB_TOKEN }}
      - uses: stats-organization/github-readme-stats-action@v2
        with:
          card: stats
          options: username=${{ github.repository_owner }}&show_icons=true&theme=dark
          path: profile/stats-dark.svg
          token: ${{ secrets.GITHUB_TOKEN }}
      - name: Commit cards
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add profile/*.svg
          git commit -m "Update README cards" || exit 0
          git push
Enter fullscreen mode Exit fullscreen mode

Then in your README:

![Stats](./profile/stats.svg)
![Top Languages](./profile/top-langs.svg)
Enter fullscreen mode Exit fullscreen mode

To include private repo stats, create a PAT with the repo and read:user scopes. Store it as a repository secret and use it in place of GITHUB_TOKEN. Never paste the token into the YAML.

Streak card. Add .github/workflows/streak-stats.yml, following the Streak Stats README:

      - name: Generate streak stats
        uses: DenverCoder1/github-readme-streak-stats@v1
        with:
          options: user=${{ github.repository_owner }}&theme=default&disable_animations=true
          path: profile/streak.svg
          token: ${{ secrets.STREAK_STATS_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

(Use the same checkout and commit steps as above.) The token line is only needed for private contributions. The README says to use a PAT with the repo scope, stored as a secret.

The catch: the cards only update when the workflow runs, once a day here. For a profile README, that's usually fine.

Step 4: Self-host on Vercel

If you want cards that update live, deploy your own instance:

  1. Fork the repo. The original README still has a Vercel guide, and GitHub Stats Extended has its own deploy docs.
  2. Import the fork into Vercel.
  3. Create a GitHub PAT and add it as an environment variable named PAT_1.
  4. Deploy, then swap the domain in your README:
![Stats](https://YOUR-APP.vercel.app/api?username=YOUR_USERNAME&cache_seconds=21600)
Enter fullscreen mode Exit fullscreen mode

That last step trips people up. #4747 covers cases where a self-hosted fork still looked broken because the README still pointed at the public URL. Check the URL.

On caching: cache_seconds takes values from 21600 to 86400, and the default is 21600. On your own instance, you can set the CACHE_SECONDS environment variable instead. On Vercel's free plan, keep in mind that your own usage counts against your own limits.

Step 5: Top languages card looks wrong

Two things come up a lot. The card only looks at your first 100 repos, and by default it ranks languages by byte count. One big Jupyter notebook can push everything else off the card.

![Top Langs](https://YOUR-APP.vercel.app/api/top-langs/?username=YOUR_USERNAME&hide=jupyter%20notebook&exclude_repo=old-fork&size_weight=0.5&count_weight=0.5)
Enter fullscreen mode Exit fullscreen mode

size_weight=0.5&count_weight=0.5 is the combination the README recommends. It weighs bytes and repo count together. To stop GitHub from counting notebooks at all, add a .gitattributes file to that repo:

*.ipynb linguist-vendored
Enter fullscreen mode Exit fullscreen mode

Step 6: The boring causes

Before you change anything else, check these:

  • A typo in the username, or a stray \& copied from a doc.
  • user= vs username=. Streak Stats uses user, github-readme-stats uses username.
  • A renamed account.
  • A cached old version. Wait for the cache to expire before you assume it's broken.

For dark/light mode, use the light and dark SVGs the workflow writes above:

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="./profile/stats-dark.svg" />
  <img src="./profile/stats.svg" alt="GitHub stats" />
</picture>
Enter fullscreen mode Exit fullscreen mode

Alternatives

If you'd rather not maintain a workflow at all, there are a few options. GitHub Stats Extended is the maintained successor and has its own public instance. The two GitHub Actions above are the most robust free option. Community-run public instances exist too, but they're third-party and nobody promises they'll stay up.

Full disclosure: I work on GitHubCard. GitHubCard is a hosted card editor: you design stats, top languages, streak and other widgets as one card, then embed it with a single line:

![GitHub profile card](https://githubcard.com/YOUR_USERNAME.svg)
Enter fullscreen mode Exit fullscreen mode

It's a hosted service too, so the same logic applies: if the card has to be up 100% of the time, a static SVG committed by an Action is still the safest choice.

Sources (accessed Oct 14, 2026)

Last verified: Oct 14, 2026.

Top comments (0)