Better GitHub statistics images for your profile, with stats from private and public repos

Overview

GitHub Stats Visualization

Generate visualizations of GitHub user and repository statistics using GitHub Actions.

This project is currently a work-in-progress; there will always be more interesting stats to display.

Background

When someone views a profile on GitHub, it is often because they are curious about a user's open source projects and contributions. Unfortunately, that user's stars, forks, and pinned repositories do not necessarily reflect the contributions they make to private repositories. The data likewise does not present a complete picture of the user's total contributions beyond the current year.

This project aims to collect a variety of profile and repository statistics using the GitHub API. It then generates images that can be displayed in repository READMEs, or in a user's Profile README.

Since the project runs on GitHub Actions, no server is required to regularly regenerate the images with updated statistics. Likewise, since the user runs the analysis code themselves via GitHub Actions, they can use their GitHub access token to collect statistics on private repositories that an external service would be unable to access.

Disclaimer

If the project is used with an access token that has sufficient permissions to read private repositories, it may leak details about those repositories in error messages. For example, the aiohttp library—used for asynchronous API requests—may include the requested URL in exceptions, which can leak the name of private repositories. If there is an exception caused by aiohttp, this exception will be viewable in the Actions tab of the repository fork, and anyone may be able to see the name of one or more private repositories.

Due to some issues with the GitHub statistics API, there are some situations where it returns inaccurate results. Specifically, the repository view count statistics and total lines of code modified are probably somewhat inaccurate. Unexpectedly, these values will become more accurate over time as GitHub caches statistics for your repositories. Additionally, repositories that were last contributed to more than a year ago may not be included in the statistics due to limitations in the results returned by the API.

For more information on inaccuracies, see issue #2, #3, and #13.

Installation

  1. Create a personal access token (not the default GitHub Actions token) using the instructions here. Personal access token must have permissions: read:user and repo. Copy the access token when it is generated – if you lose it, you will have to regenerate the token.
    • Some users are reporting that it can take a few minutes for the personal access token to work. For more, see #30.
  2. Click here to create a copy of this repository. Note: this is not the same as forking a copy because it copies everything fresh, without the huge commit history.
  3. If this is the README of your fork, click this link to go to the "Secrets" page. Otherwise, go to the "Settings" tab of the newly-created repository and go to the "Secrets" page (bottom left).
  4. Create a new secret with the name ACCESS_TOKEN and paste the copied personal access token as the value.
  5. It is possible to change the type of statistics reported.
    • To ignore certain repos, add them (in owner/name format e.g., jstrieb/github-stats) separated by commas to a new secret—created as before—called EXCLUDED.
    • To ignore certain languages, add them (separated by commas) to a new secret called EXCLUDED_LANGS.
    • To show statistics only for "owned" repositories and not forks with contributions, add an environment variable (under the env header in the main workflow) called EXCLUDE_FORKED_REPOS with a value of true.
  6. Go to the Actions Page and press "Run Workflow" on the right side of the screen to generate images for the first time. The images will be periodically generated every hour, but they can be manually regenerated by manually running the workflow.
  7. Check out the images that have been created in the generated folder.
  8. To add your statistics to your GitHub Profile README, copy and paste the following lines of code into your markdown content. Change the username value to your GitHub username.
    ![](https://github.com/username/github-stats/blob/master/generated/overview.svg)
    ![](https://github.com/username/github-stats/blob/master/generated/languages.svg)
  9. Link back to this repository so that others can generate their own statistics images.
  10. Star this repo if you like it!

Support the Project

There are a few things you can do to support the project:

  • Star the repository (and follow me on GitHub for more)
  • Share and upvote on sites like Twitter, Reddit, and Hacker News
  • Report any bugs, glitches, or errors that you find

These things motivate me to to keep sharing what I build, and they provide validation that my work is appreciated! They also help me improve the project. Thanks in advance!

If you are insistent on spending money to show your support, I encourage you to instead make a generous donation to one of the following organizations. By advocating for Internet freedoms, organizations like these help me to feel comfortable releasing work publicly on the Web.

Related Projects

Comments
  • Initial commit failed with Error: Process completed with exit code 128.

    Initial commit failed with Error: Process completed with exit code 128.

    I followed the instructions in the README but the GitHub workflow failed. Here is some information.

    My personal access token permissions

    image

    Step: generate images

    Run python3 --version
    Python 3.8.12
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned [20](https://github.com/tanjuntao/github-stats/runs/6331838497?check_suite_focus=true#step:6:20)2. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    A path returned 202. Retrying...
    There were too many 202s. Data for this repository will be incomplete.
    

    Step: commit to the repo

    Run git config --global user.name "jstrieb/github-stats"
    [master adc985c] Update generated files
     2 files changed, 33 insertions(+), [12](https://github.com/tanjuntao/github-stats/runs/6331838497?check_suite_focus=true#step:7:12)3 deletions(-)
    remote: Permission to tanjuntao/github-stats.git denied to github-actions[bot].
    fatal: unable to access 'https://github.com/tanjuntao/github-stats/': The requested URL returned error: 403
    Error: Process completed with exit code 128.
    

    I don't get where the problem comes from, would you please provide some suggestions?

    opened by tanjuntao 14
  • Builds failing - REST API returning 202 and never 200.

    Builds failing - REST API returning 202 and never 200.

    Queries erroring with code 202.

    When the Action to generate images is run, it sits endlessly and keeps throwing out "A path returned 202. Retrying..." and "There were too many 202s. Data for this repository will be incomplete.".

    I suspect this might be a side effect of the changes to the OAuth API, as shown here: https://www.githubstatus.com/incidents/6gpzw3mdnkwj Status on the API itself seems fine.

    I have checked in multiple of the forked repos and have seen the same issue occurring, after spending ages trying to figure out if it was mine 😂

    opened by stevenjwheeler 14
  • Ability to output a debug dump

    Ability to output a debug dump

    Some days ago, a new language added in my languages.svg file.

    The thing is, the only "link" I have with this language is that I recently viewed this repo, which is written in Zig: https://github.com/Jarred-Sumner/bun

    I know that I can exclude this language (because I don't want to have it in my stats), but I'd be curious to have some logs or even enable some kind of debug dump file, to see where does this language comes from in my stats. What repo is responsible for adding this language in my stats.

    I tried to run this template repo locally, but it generated empty images. Even when I set ACCESS_TOKEN and GITHUB_ACTOR as environment variables.

    opened by Drarig29 11
  • Failed to commit to repo

    Failed to commit to repo

    Workflow action fails after making a commit.

    Link to failed action log: https://github.com/yooksi/github-stats/runs/1885488408?check_suite_focus=true#step:7:1

     [master 2e497c2] Update generated files
     2 files changed, 33 insertions(+), 51 deletions(-)
    To https://github.com/yooksi/github-stats
     ! [rejected]        master -> master (fetch first)
    error: failed to push some refs to 'https://github.com/yooksi/github-stats'
    hint: Updates were rejected because the remote contains work that you do
    hint: not have locally. This is usually caused by another repository pushing
    hint: to the same ref. You may want to first integrate the remote changes
    hint: (e.g., 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    Error: Process completed with exit code 1.
    
    opened by matshou 9
  • Still not so convenient

    Still not so convenient

    It still need to add this files to the repo, even to every repo so that the stats can be updated.

    But it's possible to checkout another user's repo in GitHub Action...why not just checkout this repo and use the python source files inside?

    opened by PassionPenguin 8
  • Generate images error

    Generate images error

    Getting this error:

    Run python3 --version
    Python 3.8.5
    Traceback (most recent call last):
      File "generate_images.py", line 105, in <module>
        asyncio.run(main())
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/asyncio/runners.py", line 43, in run
        return loop.run_until_complete(main)
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
        return future.result()
      File "generate_images.py", line 101, in main
        await asyncio.gather(generate_languages(s), generate_overview(s))
      File "generate_images.py", line 41, in generate_overview
        changed = (await s.lines_changed)[0] + (await s.lines_changed)[1]
      File "/home/runner/work/github-stats/github-stats/github_stats.py", line 435, in lines_changed
        r = await self.queries.query_rest(f"/repos/{repo}/stats/contributors")
      File "/home/runner/work/github-stats/github-stats/github_stats.py", line 93, in query_rest
        return r.json()
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/site-packages/requests/models.py", line 898, in json
        return complexjson.loads(self.text, **kwargs)
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/json/__init__.py", line 357, in loads
        return _default_decoder.decode(s)
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/json/decoder.py", line 337, in decode
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
      File "/opt/hostedtoolcache/Python/3.8.5/x64/lib/python3.8/json/decoder.py", line 355, in raw_decode
        raise JSONDecodeError("Expecting value", s, err.value) from None
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    ##[error]Process completed with exit code 1.
    
    opened by bconnorwhite 8
  • EXCLUDE_LANG not excluding Jupyter Notebooks

    EXCLUDE_LANG not excluding Jupyter Notebooks

    Hey,

    First of all, thanks for this great project!

    I may have found a bug, though (or may just be failing to find the right way to do this and need help): I can't exclude Jupyter Notebooks in EXCLUDE_LANGS.

    I've tried excluding ".ipynb" and "Jupyter Notebooks", but neither worked.

    I tested with other languages and they work just fine.

    Is this something I am doing wrong, or is it a bug?

    Thank you!

    opened by anafvana 6
  • Update github-stats

    Update github-stats

    Resolves #50 Resolves #39 Resolves #20 Resolves #19 Resolves #6

    This pull request includes:

    • numerous additional statistics:
      • percentage of total code changes
      • repository collaborators
      • repository contributors
      • repository clones
      • pull requests
      • issues
    • changes to images
      • adjusted sizes to fit additional statistics and for displaying more languages
      • dark mode support (based on @idiotWu and @rahul-jha98 forked/generated github-stats)
    • changes to workflows (based on the workflow used in the generated github-stats by @idiotWu)
      • one for when changes are pushed to the master branch, which also stars the other one below
      • another one for daily auto updates to the statistics and images in another designated branch
        • this workflow has a 5 minute delay for when changes are pushed to the master branch
    • additional environment variables for storing and modifying stats
      • REPO_VIEWS
        • this is for adding to the view count fetched from API for days after the REPO_LAST_VIEW date
      • REPO_LAST_VIEW
        • this is the date the REPO_VIEWS are last updated - it can be any day but today
      • FIRST_VIEWED
        • this is the earliest date view counts are fetched from the API, or a user enters manually
      • MAINTAIN_REPO_VIEWS
        • boolean for if repository views are maintained beyond the 14-day limit and REPO_VIEWS is included, or not - true by default
      • REPO_CLONES
        • this is for adding to the clone count fetched from API for days after the REPO_LAST_CLONED date
      • REPO_LAST_CLONED
        • this is the date the REPO_CLONES are last updated - it can be any day but today
      • FIRST_CLONED
        • this is the earliest date clone counts are fetched from the API, or a user enters manually
      • MAINTAIN_REPO_CLONES
        • boolean for if repository clones are maintained beyond the 14-day limit and REPO_CLONES is included, or not - true by default
      • MORE_COLLABS
        • takes an integer value representing collaborators that are otherwise not represented on GitHub
    • JSON DB as a second resort for when user's don't use environment variables
      • the DB is only modified in the branch actions are pushed to, and is unchanged in the main branch
    • most other changes are PEP8, added constants, move files to packages, etc.

    Note:

    • Every push to the master branch wil reset the DB (unless view and clone data are stored in environment vriables)
    • Following enviornment variables for view and clone data being read and stored to DB, if these environment variables are not removed or updated within the next 14 days there errors may result in the visualized statistics

    The following are the generated transparent images from a generated repo with these changes: R055A/GitStats

    GitStats Overview - LightGitStats Overview - DarkGitStats Languages - LightGitStats Languages - Dark

    They may not fit side-by-side in the pull request, but they do in a README.md.

    Change the theme between day/light and night/dark modes to see the generated images in each.

    opened by R055A 6
  • Too many stars ?

    Too many stars ?

    Hi,

    I tried your repo, and the result tells me I have lots of stars & forks, it's a little bit unrealistic

    Are you counting the starts of all repositories I contributed to ?

    image

    I think these are the correct values:

    ⭐    Total Stars:                            3,183
    ➕    Total Commits:                          2,512
    📦    Contributed to:                            42
    

    source api requests

    opened by bokub 6
  • Java Code gets displayed as Kotlin and vice versa

    Java Code gets displayed as Kotlin and vice versa

    As the title says, the extension counts all my Java code as Kotlin and vice versa. Initially, it did not create this issue (especially when I was coding on Java exclusively), but I started to do some Android Development stuff on Kotlin which messed it up.

    Here's a screenshot from right now:

    Here's a screenshot from an earlier commit:

    I only have one repository in Kotlin, so the latter seems more correct (plus most of my code is still on Java).

    opened by suobset 5
  • Counting stars and forks from forks

    Counting stars and forks from forks

    Hi!

    I just generated stats for my profile, and it resulted in the following: image (the true file is located here)

    The stats looks strange, because I counted and I don't know if I even have 10 stars, and it says I got more than 2000. Does the action count stars and forks including forks? I realize this might be a design decision, but I figured I might ask.

    Anyway, congratz on the tool! It looks nice and it has valuable information such as repository views and all-time contributions.

    opened by GCrispino 5
  • Option to disable stats from private repos

    Option to disable stats from private repos

    I think it's a cool feature that data from private repos is also considered. However, I would like to only include data from my public repos. Is this possible?

    opened by fritzrehde 0
  • Clarify needed permissions

    Clarify needed permissions

    Current instructions state on step 2: "Personal access token must have permissions: read:user and repo." When we are creating a New fine-grained personal access token , we have many permissions to chose from. It's not clear what permissions need to be added for this to work. There is no read:user or repo.

    image

    opened by tiagonmas 0
  • No name's github stats

    No name's github stats

    I am trying to implement the stats on readme. I have created all the files and folders and yaml file but I am getting No name's github stats and no stats. I am an attaching the image for reference:

    Screenshot 2022-07-06 at 2 58 34 PM

    This is my main.yml file:

    # This is a basic workflow to help you get started with Actions
    
    name: Generate Stats Images
    
    # Controls when the action will run. Triggers the workflow on push events
    on:
      push:
      schedule:
        - cron: "0 0 * * *"
      workflow_dispatch:
    
    permissions:
      contents: write
    
    # A workflow run is made up of one or more jobs that can run sequentially or in
    # parallel
    jobs:
      # This workflow contains a single job called "build"
      build:
        # The type of runner that the job will run on
        runs-on: ubuntu-latest
    
        # Sequence of tasks that will be executed as part of the job
        steps:
        # Checks-out repository under $GITHUB_WORKSPACE, so the job can access it
        - uses: actions/checkout@v2
    
        # Run using Python 3.8 for consistency and aiohttp
        - name: Set up Python 3.8
          uses: actions/setup-python@v2
          with:
            python-version: '3.8'
            architecture: 'x64'
    
        # Cache dependencies. From:
        # https://github.com/actions/cache/blob/master/examples.md#python---pip
        - uses: actions/cache@v2
          with:
            path: ~/.cache/pip
            key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
            restore-keys: |
              ${{ runner.os }}-pip-
    
    
        # Install dependencies with `pip`
        - name: Install requirements
          run: |
            python3 -m pip install --upgrade pip setuptools wheel
            python3 -m pip install -r requirements.txt
    
        - name: Generate images
          run: |
            python3 --version
            python3 generate_images.py
          env:
            ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
            GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
            EXCLUDE_FORKED_REPOS: true
    
        # Commits all changed files to the repository
        - name: Commit to the output branch of repo
          run: |
            git config --global user.name "reveurguy"
            git config --global user.email "[email protected]"
            git add .
            git commit -m 'temp commit' || echo
            git checkout output1 2>/dev/null || git checkout --orphan output1 && git rm -rf . && git checkout master -- generated/
            # "echo" returns true so the build succeeds, even if no changed files
            git commit -m 'Update generated files' || echo
            git push origin output1 -f
    
    opened by reveurguy 4
  • Display all languages

    Display all languages

    I am a programming language collector. This may seem like a crazy question, but is there a way to display ALL languages in languages.svg instead of just the top 13? It seems to have picked up all the languages I wanted it to, they just don't all show, not even as other % (yes, I know a lot of lag would be involved, I am just wondering if it is possible)

    opened by seanpm2001 0
  • Overflow problem !

    Overflow problem !

    In small width devices some content of language.svg is overflowing. I was trying to fix it and if found the bug.

    Problem:

    foreignObject {
      width: calc(100% - 10px - 32px);
      height: calc(100% - 10px - 24px);
    }
    

    vivo-v5s-5 5-720 x 1280

    Fix:

    But without the height and width property everything is fine.

    foreignObject {
    }
    

    dddd

    opened by NazmusSayad 1
Owner
Jacob Strieb
Programmer • Hacker • Public Interest Technologist
Jacob Strieb
Add your recently blog and douban states in your GitHub Profile

Add your recently blog and douban states in your GitHub Profile

Bingjie Yan 4 Dec 12, 2022
Script to quickly get the metrics from Github repos to analyze.

commit-prefix-analysis Script to quickly get the metrics from Github repos to analyze. Setup Install the Github CLI. You'll know its working when runn

David Carpenter 1 Dec 17, 2022
GitHub saver for stargazers, forks, repos

GitHub backup repositories Save your repos and list of stargazers & list of forks for them. Pure python3 and git with no dependencies to install. GitH

Alexander Kapitanov 23 Aug 21, 2022
A python tool that creates issues in your repos based on TODO comments in your code

Krypto A neat little sidekick python script to create issues on your repo based on comments left in the code on your behalf Convert todo comments in y

Alex Antoniou 4 Oct 26, 2021
Shows VRML team stats of all players in your pubs

VRML Team Stat Searcher Displays Team Name, Team Rank (Worldwide), and tier of all the players in your pubs. GUI WIP: Only username search works (for

Hamish Burke 2 Dec 22, 2022
Get the stats of a (or more) Hypixel player(s)

Hypixel_Stats Get the statistics of a (or more) Hypixel player(s) Who needs this? Everyone who plays a lot of Minecraft and often plays on mc.hypixel.

Finnomator 1 Feb 12, 2022
Mail Me My Social Media stats (SoMeMailMe)

Mail Me My Social Media follower count (SoMeMailMe) TikTok only show data 60 days back in time. With this repo you can easily scrape your follower cou

Daniel Wigh 1 Jan 7, 2022
Osu statistics right on your desktop, made with pyqt

Osu!Stat Osu statistics right on your desktop, made with Qt5 Credits Would like to thank these creators for their projects and contributions. ppy, osu

Aditya Gupta 21 Jul 13, 2022
GitHub Actions Version Updater Updates All GitHub Action Versions in a Repository and Creates a Pull Request with the Changes.

GitHub Actions Version Updater GitHub Actions Version Updater is GitHub Action that is used to update other GitHub Actions in a Repository and create

Maksudul Haque 42 Dec 22, 2022
Dicionario-git-github - Dictionary created to help train new users of Git and GitHub applications

Dicionário ?? Dicionário criado com o objetivo de auxiliar no treinamento de nov

Felippe Rafael 1 Feb 7, 2022
Create or join a private chatroom without any third-party middlemen in less than 30 seconds, available through an AES encrypted password protected link.

PY-CHAT Create or join a private chatroom without any third-party middlemen in less than 30 seconds, available through an AES encrypted password prote

null 1 Nov 24, 2021
Persian Kaldi profile for Rhasspy built from open speech data

Persian Kaldi Profile A Rhasspy profile for Persian (fa). Installation Get started by first installing Vosk: # Create virtual environment python3 -m v

Rhasspy 12 Aug 8, 2022
Tool that adds githuh profile views to ur acc

Tool that adds githuh profile views to ur acc

Lamp 2 Nov 28, 2021
Sample python script for monitoring Rocketchat database and get statistics of users.

rocketchat-DB-monitoring Sample python script for monitoring Rocketchat database and get statistics of users. 1. Update python: yum check-update && yu

Mojtaba Taleghani 1 Apr 12, 2022
skimpy is a light weight tool that provides summary statistics about variables in data frames within the console.

skimpy Welcome Welcome to skimpy! skimpy is a light weight tool that provides summary statistics about variables in data frames within the console. Th

null 267 Dec 29, 2022
Library for Memory Trace Statistics in Python

Memory Search Library for Memory Trace Statistics in Python The library uses tracemalloc as a core module, which is why it is only available for Pytho

Memory Search 1 Dec 20, 2021
Better firefox bookmarks script for rofi

rofi-bookmarks Small python script to open firefox bookmarks with rofi. Features Icons! Only show bookmarks in a specified bookmark folder Show entire

null 32 Nov 10, 2022
Daily knowledge pills to get better in Python.

Python daily pills Daily knowledge pills to get better Python code. Why Does your Python code suffers of any of this symptoms? Incorrect Indentation I

Jeferson Vaz dos Santos 35 Sep 19, 2022
This is a fork of the BakeTool with some improvements that I did to have better workflow.

blender-bake-tool This is a fork of the BakeTool with some improvements that I did to have better workflow. 99.99% of work was done by BakeTool team.

Acvarium 3 Oct 4, 2022