How can I export all my issues from an Enterprise GitHub repository to an Excel file? I have tried searching many Stack Overflow answers but did not succeed. I tried this solution too (exporting Git issues to CSV and getting "ImportError: No module named requests" errors. Is there any tool or any easy way to export all the issues to Excel?
-
You will need to use the API to iterate over every Repository you want to export data for. I would suggest using the ruby [octokit](https://github.com/octokit/octokit.rb) as a quick way of interacting with GitHub. This question, as is, will likely be downvoted unless you can add more code or detail of what you have tried. – osowskit Dec 29 '16 at 00:14
15 Answers
To export from a private repo using curl, you can run the following:
curl -i https://api.github.com/repos/<repo-owner>/<repo-name>/issues --header "Authorization: token <token>"
The token can be generated under Personal access tokens
Inspect the API description for all details.
-
I am only getting all the OPEN issues. Is there a query parameter that specifies all issues, whether open or closed? – AgilePro Apr 13 '18 at 00:15
-
13`https://api.github.com/repos/
/ – mbesso Apr 13 '18 at 08:10/issues?state=all`will get you all issues. Note that also pull requests are treated as issues so you will get those too. All query parameters are [here](https://developer.github.com/v3/issues/#list-issues-for-a-repository). -
1why the ```-i``` flag? wouldn't it be better without so that your output is just json? – mwag May 01 '19 at 22:06
-
1Password authentication is going to be deprecated: https://developer.github.com/changes/2020-02-14-deprecating-password-auth/ – Eric Stdlib May 07 '20 at 04:04
-
2Any issues on how to do this if you have two factor authentication setup? – Stephane Grenier Jul 25 '20 at 05:06
-
6As mentioned, this is deprecated and doesn't work if you have 2FA enabled. The proper way to do this is to create a personal access token at https://github.com/settings/tokens and then pass that value as a header: `curl -i https://api.github.com/repos/
/ – tom-james-watson Nov 04 '20 at 18:09/issues --header "Authorization: token "` -
At least in my experience with a private repo, you'll need a Personal Access Token with the "repo" scope on it (full control of private repositories), otherwise you'll encounter a "404 Not Found" when attempting this command. – Michael Innes Dec 21 '21 at 18:41
With the official GitHub CLI you can easily export all issues into a CSV format.
brew install gh
Log in:
gh auth login
Change directory to a repository and run this command:
gh issue list --limit 1000 --state all | tr '\t' ',' > issues.csv
In the European .csv files the separator is a semicolon ';'
, not a comma. Modify the separator as you want.

- 1,070
- 10
- 8
-
2This was helpful to me, though the default csv uses comma deliminators, and it is useful to show the use of sending output to the file `gh issue list --limit 1000 --state all | tr '\t' ',' > my_issues.csv` – Rob Oct 29 '20 at 14:59
-
2Tks. Pretty good! Note: For me, to open CSV correctly on Excel on MacOS, I replaced "," to ";" on script line. – jeff_drumgod Nov 10 '20 at 09:58
-
2Thank you. `gh` just changed my life. ```MAX_NUM=`gh issue list --limit 1 --json number | jq ".[].number"`; for n in `seq 1 $MAX_NUM`; do gh issue view $n --json assignees,author,body,closed,closedAt,comments,createdAt,id,labels,milestone,number,projectCards,reactionGroups,state,title,updatedAt,url >> github-dump.json; done``` – John Lehmann Jan 01 '22 at 14:49
-
1Thanks; USA Excel here...I got a cleaner csv with this: `gh issue list --limit 1000 --state all | tr ',' ' ' | tr '\t' ',' > issues.csv` – C C Feb 22 '22 at 22:34
-
thank you for sharing this. This is great and much better than the traditional terminal. A lot faster to see the issue and create PRs. – Athar Mar 06 '22 at 23:50
-
For some reason this would only export the first 13 issues out of 93 and I couldn't work out what it was and any comma in the text splits the text to new columns so job titles span different and multiple columns. For me, the Excel Power Query below works better and does not require anything to be installed and everything is in consistent columns. – Robin Wilson Feb 10 '23 at 09:26
The hub command-line wrapper for github makes this pretty simple.
You can do something like this:
$ hub issue -f "%t,%l%n" > list.csv
which gives you something like this
$ more issue.csv
Issue 1 title, tag1 tag2
Issue 2 title, tag3 tag2
Issue 3 title, tag1

- 2,262
- 2
- 20
- 24
-
9This is absolutely the best method for doing this that I tried from these answers. To give you an example of how powerful this is, the following command `hub issue -s all -d 2019-08-20 -o updated --include-pulls -f "%U|%t|%S|%cI|%uI|%L%n" > issues.csv` exported all issues updated since 2019-08-20 including pull requests, and output them as a "|" separated csv. – Richard J Jan 28 '20 at 11:10
-
3Agreed this is a great method. What wasn't initial clear to me was: 1) Run the command within the folder containing the cloned repository of interest. 2) Don't redirect to `list.csv` the first time you run `hub` as it could be asking for username and password so will appear to hang. – Nick Ager Jan 14 '21 at 15:20
-
2If, instead of CSV, you want to get all the comments for each issue and preserve the formatting: `hub issue -s all -f "%I%n" | xargs -I % sh -c 'hub issue show % | dos2unix > %.md'`. This results in one markdown file for each issue. dos2unix cleans up the newlines in the export. – Christian Long Feb 25 '22 at 17:01
-
hub looks like a nice solution, however, noting that the docs say hub requires use of https protocol, not ssh. It is also a mac only solution. – truedat101 Oct 16 '22 at 18:56
-
@truedat101 - The docs on the [github repo](https://github.com/mislav/hub) have instructions for a windows install and how to use ssh. – chip Jun 25 '23 at 18:59
If that is a one-time task, you may play around with GitHub WebAPI. It allows to export the issues in JSON format. Then you can convert it to Excel (e.g. using some online converter).
Just open the following URL in a browser substituting the {owner}
and {repo}
with real values:
https://api.github.com/repos/{owner}/{repo}/issues?page=1&per_page=100

- 2,528
- 2
- 15
- 32
-
10Trying this, it only works for public repositories (gives a "not found" error for private repos). It also does not include the comments, though it does tell you how many comments there are. – Jason Jul 11 '17 at 16:11
-
1@Jason Have you found any way to also download comments, and their attachments? – Nicolas Feb 18 '18 at 02:24
-
1@NicolasMaltais the comments are available through the APi too,so there will be an endpoint for that (details here https://developer.github.com/v3/issues/comments/). Attachments are all referenced using markdown tags, so you will need to parse those to get the URLs for the attachments, and download those separately. If you are rebuilding the issues and comments somewhere else, then you would probably need to modify those URLs to point to your new attachment storage. – Jason Feb 19 '18 at 10:11
It is unfortunate that github.com does not make this easier.
In the mean time, if you have jq and curl, you can do this in two lines using something like the following example that outputs issue number, title and labels (tags) and works for private repos as well (if you don't want to filter by label, just remove the labels={label}&
part of the url). You'll need to substitute $owner, $repo, $label, and $username:
# with personal access token = $PAT
echo "number, title, labels" > issues.csv
curl "https://api.github.com/repos/$owner/$repo/issues?labels=$label&page=1&per_page=100" -u "$username:$PAT" \
| jq -r '.[] | [.number, .title, (.labels|map(.name)|join("/"))]|@csv' >> issues.csv
# without PAT (will be prompted for password)
echo "number, title, labels" > issues.csv
curl "https://api.github.com/repos/$owner/$repo/issues?labels=$label&page=1&per_page=100" -u "$username" \
| jq -r '.[] | [.number, .title, (.labels|map(.name)|join("/"))]|@csv' >> issues.csv
Note that if your data exceeds 1 page, it may require additional calls.

- 3,782
- 4
- 16
- 33

- 3,557
- 31
- 38
-
To add your OTP, simply add a header to the curl request as follows: `-H "GitHub-OTP: XXXXXX"` – Adam Reis Jan 17 '20 at 00:15
-
Can this command be extended to also fetch the body of each issue? – Camille Goudeseune Jan 30 '20 at 21:42
-
When I tried this just now, github emailed me: You recently used a password to access an endpoint through the GitHub API using curl/7.35.0. We will deprecate basic authentication using password to this endpoint soon: ... We recommend using a personal access token (PAT) with the appropriate scope to access this endpoint instead. Visit https://github.com/settings/tokens for more information. – Camille Goudeseune Jan 30 '20 at 21:51
-
1Thank you! I've updated the answer to also provide the syntax when using a PAT – mwag Feb 02 '20 at 20:20
-
1@CamilleGoudeseune assuming that when you say "body" you mean comments related to the issue, in order to fetch, the command would have to be further expanded such that each entry made an additional call to the github API to fetch comments for each issue e.g. as described at https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue – mwag Feb 02 '20 at 20:29
I tried the methods described in other comments regarding exporting issues in JSON format. It worked ok but the formatting was somehow screwed up. Then I found in Excel help that it is able to access APIs directly and load the data from the JSON response neatly into my Excel sheets.
The Google terms I used to find the help I needed were "excel power query web.content GET json". I found a How To Excel video which helped a lot.
URL that worked in the Excel query (same as from other posts):
https://api.github.com/repos/{owner}/{repo}/issues?page=1&per_page=100
Personally, I also add the parameter &state=open, otherwise I need to request hundreds of pages. At one point I reached GitHub's limit on unauthenticated API calls/hour for my IP address.

- 41
- 3
You can also check out the one-liner that I created (it involves GitHub CLI and jq
)
gh issue list --limit 10000 --state all --json number,title,assignees,state,url | jq -r '["number","title","assignees","state","url"], (.[] | [.number, .title, (.assignees | if .|length==0 then "Unassigned" elif .|length>1 then map(.login)|join(",") else .[].login end) , .state, .url]) | @tsv' > issues-$(date '+%Y-%m-%d').tsv

- 3,782
- 4
- 16
- 33

- 81
- 3
-
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/31457098) – Tobias S. Apr 11 '22 at 10:46
-
`gh` GitHub CLI integrates now `jq` with `--jq
` to filter JSON output using a jq expression as documented on GitHub CLI Manual https://cli.github.com/manual/gh_issue_list. – JV conseil May 18 '22 at 14:25
I have tinkered with this for quite some time and found that Power BI is a good way of keeping the data up to date in the spreadsheet. I had to look into Power BI a little to make this work, because getting the right info out of the structured JSON fields, and collapsing lists into concatenated strings, especially for labels, wasn't super intuitive. But this Power BI query works well for me by removing all the noise and getting relevant info into an easily digestible format that can be reviewed with stakeholders:
let
MyJsonRecord = Json.Document(Web.Contents("https://api.github.com/repos/<your org>/<your repo>/issues?&per_page=100&page=1&state=open&filter=all", [Headers=[Authorization="Basic <your auth token>", Accept="application/vnd.github.symmetra-preview+json"]])),
MyJsonTable = Table.FromRecords(MyJsonRecord),
#"Column selection" = Table.SelectColumns(MyJsonTable,{"number", "title", "user", "labels", "state", "assignee", "assignees", "comments", "created_at", "updated_at", "closed_at", "body"}),
#"Expanded labels" = Table.ExpandListColumn(#"Column selection", "labels"),
#"Expanded labels1" = Table.ExpandRecordColumn(#"Expanded labels", "labels", {"name"}, {"labels.name"}),
#"Grouped Rows" = Table.Group(#"Expanded labels1", {"number","title", "user", "state", "assignee", "assignees", "comments", "created_at", "updated_at", "closed_at", "body"}, {{"Label", each Text.Combine([labels.name],","), type text}}),
#"Removed Other Columns" = Table.SelectColumns(#"Grouped Rows",{"number", "title", "state", "assignee", "comments", "created_at", "updated_at", "closed_at", "body", "Label"}),
#"Expanded assignee" = Table.ExpandRecordColumn(#"Removed Other Columns", "assignee", {"login"}, {"assignee.login"})
in
#"Expanded assignee"
I added and then removed columns in this and did not clean this up - feel free to do that before you use it. Obviously, you also have to fill in your own organization name and repo name into the URL, and obtain the auth token. I have tested the URL with a Chrome REST plugin and got the token from entering the user and api key there. You can authenticate explicitly from Excel with the user and key if you don't want to deal with the token. I just find it simpler to go the anonymous route in the query setup and instead provide the readily formatted request header.
Also, this works for repos with up to 100 open issues. If you have more, you need to duplicate the query (for page 2 etc) and combine the results.
Steps for using this query:
- in a new sheet, on the "Data" tab, open the "Get Data" drop-down
- select "Launch Power Query Editor"
- in the editor, choose "New Query", "Other Sources", "Blank query"
- now you click on "Advanced Editor" and paste the above query
- click the "Done" button on the Advanced Editor, then "Close and Load" from the tool bar
- the issues are loading in your spreadsheet and you are in business
- no crappy third-party tool needed

- 37,019
- 22
- 105
- 153
-
I wasn't able to get this to work with an Authorization header, but taking that header out and putting my username and PAT token into the "basic" section of Data Source Settings > Edit Permissions > Access Web Content dialog box did. – Daz Jul 19 '21 at 15:12
-
1The standard accept header in Github docs is now "application/vnd.github.v3+json" – Daz Jul 19 '21 at 15:13
-
After trying many approaches this is the only one that has worked well. I had to switch `Basic
` to `Token – Robin Wilson Feb 10 '23 at 09:20` for it to work. Thanks a lot for sharing. -
In order to then format the dates to dates/time Excel will recognise as dates you can add this line `#"Changed Type" = Table.TransformColumnTypes(#"Expanded assignee",{{"created_at", type datetime}, {"updated_at", type datetime}, {"closed_at", type datetime}})` – Robin Wilson Feb 10 '23 at 09:31
You can also try https://github.com/remoteorigin/git-issues-downloader but be sure to used the develop branch. The npm version and master branch is buggy.
Or you can use this patched version with
npm install -g https://github.com/mkobar/git-issues-downloader
and then run with (for public repo)
git-issues-downloader -n -p none -u none https://github.com/<user>/<repository>
or for a private repo:
git-issues-downloader -n -p <password or token> -u <user> https://github.com/<user>/<repository>
Works great.

- 21
- 5
Here is a tool that does it for you (uses the GitHub API): https://github.com/gavinr/github-csv-tools

- 6,094
- 7
- 33
- 44
You can do it using the python package PyGithub
from github import Github
token = Github('personal token key here')
repo = token.get_repo('repo-owner/repo-name')
issues = repo.get_issues(state='all')
for issue in issues:
print(issue.url)
Here I got back the URL, you can get back the content instead if you want by changing the '.URL' part. Then just export the issues links or content to CSV.

- 3,782
- 4
- 16
- 33

- 11
- 2
gh
GitHub CLI integrates now jq
with --jq <expression>
to filter JSON output using a jq expression as documented on GitHub CLI Manual https://cli.github.com/manual/gh_issue_list.
TSV
dump.
gh issue list --limit 10 --state all --json title,body --jq '["title","body"], (.[] | [.title,.body]) | @tsv' > issues-$(date '+%Y-%m-%d').tsv
CSV
dump
Surprisingly 000D
unicode character need to be filtered out with tr $'\x{0D}' ' '
.
gh issue list --limit 10 --state all --json title,body --jq '["title","body"], (.[] | [.title,.body]) | @csv' | tr $'\x{0D}' ' ' > issues-$(date '+%Y-%m-%d').csv

- 328
- 5
- 11
Export Pull Requests can export issues to a CSV file, which can be opened with Excel. It also supports GitLab and Bitbucket.
From its documentation:
Export open PRs and issues in sshaw/git-link and sshaw/itunes_store_transporter:
epr sshaw/git-link sshaw/itunes_store_transporter > pr.csv
Export open pull request not created by sshaw in padrino/padrino-framework:
epr -x pr -c '!sshaw' padrino/padrino-framework > pr.csv
It has several options for filtering what gets exported.
GitHub's JSON API can be queried from directly in Excel using Power Query. It does require some knowledge about how to convert JSON into Excel table format but that's fairly Googlable.
Here's how to first get to the data:
In Excel, on Ribbon, click Data > Get Data > From JSON. In dialog box, enter API URL ... in format similar to (add parms as you wish): https://api.github.com/repos/{owner}/{repo}/issues
A dialog box labeled "Access Web content" will appear.
On the left-hand side, click the Basic tab.
In the User name textbox, enter your GitHub username.
In the Password textbox, enter a GitHub password/Personal Access token.
Click Connect.
Power Query Editor will be displayed with a list of items that say Record.
... now Google around for how to transform accordingly so that the appropriate issue data can be displayed as a single table.

- 1
- 3
As a one-time task, building on 'hub'-based recommendation from @Chip... on a windows system with GitBash prompt already installed:
Download the latest hub executable (such as Windows 64 bit) https://github.com/github/hub/releases/ and extract it (hub.exe is in the .../bin directory).
Create a github personal access token https://github.com/settings/tokens and copy the token text string to the clipboard.
Create a text file (such as in notepad) to use as the input file to hub.exe... the first line is your github user name and on the 2nd line paste the personal access token, followed by a newline (so that both lines will processed when input to hub). Here I presume the file is infile.txt in the repository's base directory.
Run Git Bash... and remember to cd (change directory) to the repository of interest! Then enter a line like:
<path_to_hub_folder>/bin/hub.exe issue -s all -f "%U|%t|%S|%cI|%uI|%L%n" < infile.txt > outfile.csv
Then open the file with '|' as the column delimiter. (and consider deleting the personal access token on github).

- 27
- 8