123

On the CI server, I want to fetch a config file that we maintain on Github so it can be shared between many jobs. I'm trying to get this file via curl, but these approaches both fail (I get a 404):

# As advised by the oAuth docs
curl -H 'Authorization: token the_token' -L -o setup.sh https://raw.github.com/org/repo/file

# The url of the raw file after clicking to view it
curl -L https://raw.github.com/org/repo/file?login=username&token=the_token 
Matt Gibson
  • 14,616
  • 7
  • 47
  • 79

20 Answers20

169

The previous answers don't work (or don't work anymore).

You can use the V3 API to get a raw file like this (you'll need an OAuth token):

curl -H 'Authorization: token INSERTACCESSTOKENHERE' \
  -H 'Accept: application/vnd.github.v3.raw' \
  -O \
  -L https://api.github.com/repos/owner/repo/contents/path

All of this has to go on one line. The -O option saves the file in the current directory. You can use -o filename to specify a different filename.

To get the OAuth token follow the instructions here:

I've written this up as a gist as well:

EDIT: API references for the solution are as follows:

Insung Park
  • 401
  • 3
  • 15
thomasfuchs
  • 5,386
  • 2
  • 18
  • 38
  • 4
    Note that if the file is public, there's no need for the authorization token: `curl -H 'Accept: application/vnd.github.v3.raw' https://api.github.com/repos/owner/repo/contents/path` will return the raw file. – Alf Eaton Aug 22 '14 at 08:47
  • Is the `-H 'Accept: application/vnd.github.v3.raw'` necessary? I was able to access a private file without that part. – Nick Chammas Jun 12 '15 at 17:33
  • 2
    @NickChammas: without that header I get a JSON response with metadata and the actual file contents base64 encoded, rather than the file as plain text. – c24w Jul 15 '15 at 12:57
  • What if the above command gives error as curl: (56) Proxy CONNECT aborted what does that mean. – Max Aug 28 '15 at 13:45
  • @thomasfuchs I've missed something obvious with the file path. Can you explicitly define a harmless README.md file in your command to demonstrate? – fIwJlxSzApHEZIl Oct 04 '16 at 05:03
  • 4
    Note that the URL is different from the URL you'd use in a browser. I've highlighted the difference here: `https://` **`api.`** `github.com/` **`repos/`** `//` **`contents/`** `` (sorry it's a bit messy) – PJSCopeland Dec 09 '16 at 01:12
  • @Max: sounds like you need to load your proxy config into your terminal, most likely by setting an `http_proxy` environment variable or similar. – PJSCopeland Dec 09 '16 at 01:15
  • For multiple files use `-O -L ` for each link/url. Tested in a docker/linuxkit-4.19.76. – infiniteloop Sep 02 '20 at 20:11
  • 4
    This works also with a [personal access token](https://github.com/settings/tokens). The minimal set of permission that are required are `repo` and `admin:org/read:org` (on a private repository). – rlat Nov 10 '20 at 17:08
  • how can I specify a specific sha/revision of the file? – Pramod Jangam Apr 21 '21 at 11:07
  • When writing a script, if you've set up `git credential-helper`, you can get your access token in there with `-H "Authorization: token $(printf 'protocol=https\nhost=github.com\n' | git credential fill | sed -n 's/^password=//p')"`, which fetches your token from `git` so you don't need to have it in your environment or hard-coded. – Adam Azarchs Sep 03 '21 at 23:17
  • Does anybody have documentation to when this behavior was changed? Does Github have some official deprecation documentation or something? – John Magistr Mar 02 '23 at 08:15
47

Alternatively, you can use a github "personal access token" (https://github.com/settings/tokens):

TOKEN=...
curl -s https://$TOKEN@raw.githubusercontent.com/<user or organization>/<repo name>/<branch>/<path to file>/<file_name>

Example:

$ curl -s https://1bacnotmyrealtoken123beefbea@raw.githubusercontent.com/concourse/concourse/master/README.md
....
theartofrain
  • 1,710
  • 15
  • 14
  • 1
    @EM0 -- I just tried, it worked. A few things worth double-checking: 1. the host portion is `raw.githubusercontent.com`, 2. the path is `///` 3. the token needs to have `repo` access scope. – theartofrain Nov 09 '16 at 19:13
  • 1
    Yes, that's the path. I took the path from "Download" link for the file, but stripped the "?token=..." from the end and added the token. It does have repo access scope, but this only talks about public repositories. This is an organization private repository. Also, we have 2-factor authentication enabled, but I think if that's the issue it's supposed to give error 401, not 404. – EM0 Nov 09 '16 at 19:24
  • Yes, this all sounds right. The path sounds good (this is the path I get when I click "Raw", stripped of the `?token=...` param, like you said). My user also has 2-factor auth, and I am assuming we are talking about the same token scope (the `repo` checkbox on https://github.com/settings/tokens/new). For what it's worth, if the token is invalid, or doesn't have the `repo` scope, you WILL get 404 (not 401). Not sure why this is not working in your setup... – theartofrain Nov 09 '16 at 19:36
  • OK, well I guess I'll just use a link so people have to click one extra time - no big deal. Thanks for your help anyway! – EM0 Nov 09 '16 at 19:40
  • 7
    Strange thing: For me using the `curl` command as above works, but if I open the same link in the browser or try requesting it via `java.net.URL.openStream`, I get a 404... – Nightscape Jul 27 '17 at 08:37
  • 2
    This was the only way I could get it working for an internal GitHub instance in CMD. Using `curl -H 'Authorization: token $TOKEN' $file_url` always 404'd on me. I'm not sure why one works and not the other but I've never deep-dived CURL's documentation. – kayleeFrye_onDeck Jun 25 '19 at 20:29
  • This worked for me for pulling a file as a member in an organization, I couldn't get the accepted answer to work for my use case – darkvalance Dec 17 '20 at 10:24
  • It has stopped working recently. I am still trying to figure out why – Vaibhaw K Sep 18 '22 at 02:31
20

I know this is an old question, but none of the solutions proposed above worked for me. Perhaps the API has changed since then.

This worked:

curl -H 'Authorization: token [insert your token here]' -o output.txt https://raw.githubusercontent.com/[organization]/[repo]/[branch]/[path to file]

mark amos
  • 321
  • 2
  • 5
  • this is the only one that worked for me too but there's a small typo in your answer mark. it should be `[organization]/[repo]/[branch]...` – fIwJlxSzApHEZIl Apr 28 '17 at 00:47
  • Thanks, only thing that worked for me with Github Enterprise. Note the token required is a Personal Access Token. – Oliver Pearmain Jun 04 '19 at 12:34
  • @OliverPearmain did you ever try `curl -s https://PAT_VALUE@raw.github.company.com/OrgOrUser/RepoName/BranchOrCommitID/file_name.file_extension` ? That's the only thing I could ever get working, but other people in the company used this solution instead, so I'm thinking there might be some kind of config for CURL that makes it less restrictive to use `curl -s...` instead of this CLI set of parameters. – kayleeFrye_onDeck Jun 25 '19 at 21:36
11

A simpler solution is to use Official GitHub CLI gh.

  1. First you must be logged in :
gh auth login

For me, this command is not required since I'm already logged in.

  1. Then we need API URL targeting the file to download. And call gh to download it:
API_URL=https://api.github.com/repos/owner/repo/contents/path/file.ext
gh api $API_URL -H "Accept: application/vnd.github.raw" > file.ext

An real example is maybe better. Here it is to download install_linux.md from gh cli:

API_URL=https://api.github.com/repos/cli/cli/contents/docs/install_linux.md
gh api $API_URL -H "Accept: application/vnd.github.raw" > install_linux.md

In API_URL:

  • User owner is cli
  • Repository name repo is cli too
  • Path to file (path/file.ext) is docs/install_linux.md
Jean-Pierre Matsumoto
  • 1,917
  • 1
  • 18
  • 26
8

I was struggling with this for a few minutes until I realized all that is needed is to wrap the url in quotes to escape the ampersand.

curl "https://raw.github.com/org/repo/file?login=username&token=the_token"

That worked for me in my private repo.

8

Or, if you don't have a token:

curl --user [your_user] 'https://raw.github.com/path/to/file.config' > file.config

It will ask you for your password.

UPDATE: To those having 404s, you may have to create an SSH key for your machine. Refer to the SSH and GPG Keys in your Settings.

This works if you tap the Raw button on the respective file (It's a button on the top right, available after you tap the file you want to DL). Copy the URL for that raw resource. If you attempt to DL a resource that is not hosted through raw.github.com (it may have changed to raw.githubusercontent.com), it won't work.

I successfully DL'ed a resource from a personal repository, as well as non-personal one, using macOS as of Jul 14 2023 using this method.

PeqNP
  • 1,363
  • 15
  • 26
4

I've got a token from an app installation.

Previously, you could use the query ?access_token=MY_TOKEN, but that has been deprecated and eventually removed in September 2021.

In their docs on Authenticating with GitHub Apps they're saying you can clone a repo with the access token and the username x-access-token in the URL.

This also seems to work to download a raw file (the ghs_... is the token):

$> curl "https://x-access-token:ghs_4qgGKx4skAcaF3bAb3scrTkN4@raw.githubusercontent.com/Octocat/codertocat/main/README.md"
rethab
  • 7,170
  • 29
  • 46
3
  1. in browser open your github repo: click on file
  2. open Developer Tools in browser: select Network tab
  3. in browser github: click on Download button
  4. close pop-up
  5. in browser dev tools: right click on list that has file_name?token=ABAHQCAT6KG...
  6. select copy -> copy link address

    url is in format:

    https://raw.githubusercontent.com/<USERNAME>/<PATH>/<FILENAME>?token=ABAHQCAT6KGHYHMG2SLCDT243PH4I

  7. in terminal:

    wget -O myFilename https://raw.githubusercontent.com/<USERNAME>/<PATH>/<FILENAME>?token=ABAHQCAT6KGHYHMG2SLCDT243PH4I

Link is valid only for limited time or you can create your token: GitHub article

Milan Rakos
  • 1,705
  • 17
  • 24
2

I ran into an authentication error when the url was redirected to Amazon S3:

Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter...

Changing from the Authorization: token X header to the ?access_token=<token> query param worked for me.

kenorb
  • 155,785
  • 88
  • 678
  • 743
chrismo
  • 101
  • 1
  • 6
2

Surprisingly none of the answers didn't worked for me until I found a workaround.

You can use personal access token https://github.com/settings/tokens as answered by @thomasfuchs

Note : while creating a token, you must check the admin permissions. See the related issue

https://github.com/octokit/octokit.net/issues/1812

atul
  • 540
  • 4
  • 11
  • 1
    The admin hint got it working for me. Else i just received a 404. – Dave Mar 29 '20 at 04:27
  • The minimal set of permission that made it work for me on a private repo was `repo` and `admin:org/read:org`. – rlat Nov 10 '20 at 17:06
2

I was able to get it to work for github enterprise, thanks for the suggestions above. Had to take all your suggestions and try and finally i was able to make it work. These are the steps i followed to get it to work.

  1. Create personal token, followed these steps:

https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token

  1. Make sure you have minimum following permissions for the token:

    • repo (Select all under repo)
    • admin:org -> read:org (select "read:org" under "admin:org") enter image description here
  2. Use the following curl command to get the content:

curl -H "Authorization: token [yourPersonalToken]" -H "Accept: application/vnd.github.v3.raw" -o [filePath]-content.json -L https://github.[company].com/api/v3/repos/[ORG]/[REPO_NAME]/contents/[PATH_TO_FILE]/content.json?ref=[BRANCH_NAME]

Where->

 [yourPersonalToken] is the token you created.
 [filePath] is a path where you want to save the downloaded copy.
 [company] is the name of company which hosted the github enterprise.
 [ORG] is the github organization is which repo is created.
 [REPO_NAME] is the name of the repository.
 [PATH_TO_FILE] is the path where file is located.
 [BRANCH_NAME] is the name of the branch you want to use, e.g. master, develop etc.

Example:

curl -H "Authorization: token 5a86ecda9ff927baaa66fad2af5bee8" -H "Accept: application/vnd.github.v3.raw" -o C:\Downloads\manifest.json -L https://github.example.com/api/v3/repos/cms/cms_one/contents/app/data/manifest.json?ref=master
Abhinav Mishra
  • 101
  • 1
  • 5
  • This API can download a file smaller than `1 MB`, as of today. If we need download a big file, use this method: https://caludio.medium.com/how-to-download-large-files-from-github-4863a2dbba3b – Happy Jul 31 '21 at 02:45
1

We had to download files from private GitHub repos fairly often and hacky shell scripts weren't quite cutting it, so we created fetch, which is an open source, cross-platform tool that makes it easy to download source files and release assets from a git tag, commit, or branch of public and private GitHub repos.

For example, to download the file baz from version 0.1.3 of a private GitHub repo to /tmp, you would do the following:

GITHUB_OAUTH_TOKEN="your token"
fetch --repo="https://github.com/foo/bar" --tag="0.1.3" --source-path="/baz" /tmp
Yevgeniy Brikman
  • 8,711
  • 6
  • 46
  • 60
1

Just an addition to the accepted answer, If you are using Github Enterprise url is slightly different:

curl -H 'Authorization: token [your token]' \
-H 'Accept: application/vnd.github.v3.raw' \
-L https://[your domain]/api/v3/repos/[owner]/[repo-name]/contents/[path of file]
lonewarrior556
  • 3,917
  • 2
  • 26
  • 55
1
curl -H 'Authorization: token YOUR_TOKEN' \
  -H 'Accept: application/vnd.github.v4.raw' \
  -O \
  -L https://api.github.com/repos/INSERT_OWNER_HERE/INSERT_REPO_HERE/contents/PATH/TO/FILE

So if the url of the raw file (when logged in) is

https://raw.githubusercontent.com/mr_coder/my_repo_name/master/my_script


Then 
  -L https://api.github.com/repos/INSERT_OWNER_HERE/INSERT_REPO_HERE/contents/PATH/TO/FILE
becomes
  -L https://api.github.com/repos/mr_coder/my_repo_name/contents/my_script

Note: We have API v4

Rub
  • 2,071
  • 21
  • 37
1

For GitHub Enterprise and API v3, my bash solution looked like this (includes TOKEN cleanup / privacy):

TOKEN=yourTokenHere; history -d $((HISTCMD-1)) > /dev/null

curl -H "Authorization: token $TOKEN" \
  -H 'Accept: application/vnd.github.v3.raw' \
  -o file.ext \
  -L http://github.company.com/api/v3/repos/[org]/[repo]/contents/path/file.ext?ref=[branch]

unset TOKEN
Geoffrey Hudik
  • 536
  • 5
  • 9
0

I think it is a little bit dangerous and not good way to issue a personal access token which can access all repositories even just for download a single file from my private repository.

How to -

I would love to recommend using url with token for single file. Don't worry. The token string will generated by github automatically. You can get this url on your source code page.

  1. Go to source code page what you want to download via curl or wget, etc
  2. Find 'raw' button and click it. enter image description here
  3. New page opened and just copy the url. This url look like below:
    (https://raw.githubusercontent.com/USERNAME/REPONAME/BRANCHNAME/FILENAME?token=TOKENSTRING).
  4. You can download a file using this url
Tony
  • 403
  • 5
  • 7
  • 5
    Be careful, as the token appended to that url [will expire after a certain number of days](https://github.community/t/token-expiration-on-urls-to-private-repos/2958), so you can't really use this solution in production code. – V. Rubinetti Jul 21 '21 at 21:26
  • 2
    Furthermore, it seems like the token is different for each file. – Akash Agarwal Jun 15 '22 at 02:15
  • It appears to me that this token expires even faster. Ive had it refresh multiple times a day, so this really isnt a viable solution. – James Feb 16 '23 at 17:28
  • _"so this really isnt a viable solution"_ that really depends on your use case. In case the token _might_ be leaked to the public, then _"I think it is a little bit dangerous and not good way to issue a personal access token which can access all repositories even just for download a single file from my private repository"_ makes perfect sense. – xpt Mar 10 '23 at 17:01
0

A lot of the answers here either suggest to use curl and supply your own Authorization: Bearer **** header, or use the GitHub CLI (gh) to get a pre-authenticated download URL and then using curl with that URL.

However, gh supports custom headers so you can accomplish this using gh with a single request:

gh api "/repos/:owner/:repo/contents/README.md" -H "Accept: application/vnd.github.raw" > README.md
wheeler
  • 2,823
  • 3
  • 27
  • 43
-1

I tried a simple trick to open a GitHub private .iypnb file in Pycharm as well as Colab and it worked well for me.

  1. get raw text for your .ipynb file by pressing Raw button this will open some text like this.
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": []
}]
}
  1. open notepad/text editor on os(eg. windows) copy all the text to a new notepad file .

  2. save notepad as name.ipynb instead of name.txt and make save as file type All Files(.) instead of Text Documents (*.txt)

  3. finally open file in your IDE or colab.

-3

Below should work fine. A "raw" before your branch name (master in this case).

curl -L -O https://github.com/your/repo/raw/master/fetch_file.sh

-5

You can do this with a raw link.

curl -O https://raw.githubusercontent.com/owner/repo/branchname/path/to/file
Prune
  • 76,765
  • 14
  • 60
  • 81