120

I am trying to use an API query in Python. From the command line I can use curl like so:

curl --header "Authorization:access_token myToken" https://website.example/id

This gives some JSON output. myToken is a hexadecimal variable that remains constant throughout.

I would like to make this call from python so that I can loop through different ids and analyze the output. Before authentication was needed I had done that with urllib2. I have also taken a look at the requests module but couldn't figure out how to authenticate with it.

Dave Mackey
  • 4,306
  • 21
  • 78
  • 136
user1895406
  • 1,383
  • 2
  • 9
  • 10

8 Answers8

189

The requests package has a very nice API for HTTP requests, adding a custom header works like this (source: official docs):

>>> import requests
>>> response = requests.get(
... 'https://website.example/id', headers={'Authorization': 'access_token myToken'})

If you don't want to use an external dependency, the same thing using urllib2 of the standard library looks like this (source: the missing manual):

>>> import urllib2
>>> response = urllib2.urlopen(
... urllib2.Request('https://website.example/id', headers={'Authorization': 'access_token myToken'})
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
wosc
  • 2,169
  • 1
  • 13
  • 9
  • Thanks for your response. I've tried both implementations and I get an HTTP Error 401: Unauthorized. However, the command line works just fine. I've never worked with access tokens, so just to be clear: the token that I have is 40 digits of the form 3f4264ff etc. – user1895406 Dec 11 '12 at 20:04
  • 1
    Strange. What bugs me a little is the colon in the header... ah! Maybe I (or we both ;) just read that wrong. The header might be named "Authorization" and its **value** then would be "access_token long_hexadecimal_string". Want to give that a spin? – wosc Dec 12 '12 at 06:56
  • that worked! thank you so much. what i ended up typing is url = 'https://website.com/id' head = {'Authorization': 'access_token hex_string'} res=requests.get(url, headers=head) – user1895406 Dec 13 '12 at 13:27
  • 1
    This solution is deprecated or otherwise not working in default Anaconda install. – bloodrootfc May 05 '18 at 00:50
  • i've one another problem around this. I have a .py file in my code that uses requests get/put/post/delete with authToken generated by a specific POST API. this file is called in an all-time-running service's execution. So wanted to know how to refresh the token whenever a request api call gets Unauthorized error. Is there any provision with requests library to add hooks? Or i need to use some python code to refresh the token. – amitam Sep 17 '18 at 07:17
  • What is access_token myToken? From where and how can I get it? @wosc – Deep Jadia Aug 05 '19 at 02:53
  • 1
    It is an authentication token that the server uses to verify you are authorized to have access to the API. You need to obtain client credentials (username, password, API key) for the API you want to access and then send them (for example, via a get request) to the authentication server. The server returns a string that could be JSON-encoded to your client and you then use that as a token in your API calls. Search for JWT or OAuth to do some more reading and view some examples. – Filippos Zofakis Aug 29 '19 at 14:27
  • As @Sowmiya Ragu pointed below, sometimes it's not 'access_token' but 'Bearer'. `response = requests.get( 'https://website.com/id', headers={'Authorization': 'Bearer myToken'})` . Not sure if this is a version or specific sever's config isuue. – SwissNavy Jan 28 '20 at 11:10
  • `myToken = 'aoisjd0910293jijaosjd09j092j091j0asdpo'` `response = requests.get( 'https://website.com/id', headers={'Authorization': 'Token myToken'})` – Aseem Mar 09 '20 at 03:50
45

I had the same problem when trying to use a token with Github.

The only syntax that has worked for me with Python 3 is:

import requests

myToken = '<token>'
myUrl = '<website>'
head = {'Authorization': 'token {}'.format(myToken)}
response = requests.get(myUrl, headers=head)
bloodrootfc
  • 1,133
  • 12
  • 10
25
>>> import requests
>>> response = requests.get('https://website.com/id', headers={'Authorization': 'access_token myToken'})

If the above doesnt work , try this:

>>> import requests
>>> response = requests.get('https://api.buildkite.com/v2/organizations/orgName/pipelines/pipelineName/builds/1230', headers={ 'Authorization': 'Bearer <your_token>' })
>>> print response.json()
Sowmiya Ragu
  • 361
  • 4
  • 5
  • 2
    I had the same issue this week and what ended up working for me was the Authorization bearer option. Not sure why there's a difference, but thanks for providing that option for me to try and successfully get working! – Ryan Harris Jan 31 '20 at 13:05
  • 1
    @SowmiyaRagu the second part works for me `Bearer ` while the first doesn't because the response is as if the request is not authenticated. – hydradon Feb 05 '20 at 17:46
  • JULY 2022 : OPTION 2 WORKS ON PYTHON REQUESTS = 2.28.1 – Koops Jul 18 '22 at 05:50
  • access_token does not work because it is deprecated in python3 – Aanish Amir Waseem Sep 20 '22 at 21:29
12
import requests

BASE_URL = 'http://localhost:8080/v3/getPlan'
token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImR"

headers = {'Authorization': "Bearer {}".format(token)}
auth_response = requests.get(BASE_URL, headers=headers)

print(auth_response.json())

Output :

{
"plans": [
    {
        "field": false,
        "description": "plan 12",
        "enabled": true
    }
  ]
}
Shivam Bharadwaj
  • 1,864
  • 21
  • 23
11

A lot of good answers already, but I didn't see this option yet:

If you're using requests, you could also specify a custom authentication class, similar to HTTPBasicAuth. For example:

from requests.auth import AuthBase


class TokenAuth(AuthBase):
    def __init__(self, token, auth_scheme='Bearer'):
        self.token = token
        self.auth_scheme = auth_scheme

    def __call__(self, request):
        request.headers['Authorization'] = f'{self.auth_scheme} {self.token}'
        return request

This could be used as follows (using the custom auth_scheme from the example):

response = requests.get(
    url='https://example.com', 
    auth=TokenAuth(token='abcde', auth_scheme='access_token'),
)

This may look like a more complicated way to set the Request.headers attribute, but it can be advantageous if you want to support multiple types of authentication. Note this allows us to use the auth argument instead of the headers argument.

djvg
  • 11,722
  • 5
  • 72
  • 103
6

Have you tried the uncurl package (https://github.com/spulec/uncurl)? You can install it via pip, pip install uncurl. Your curl request returns:

>>> uncurl "curl --header \"Authorization:access_token myToken\" https://website.com/id"

requests.get("https://website.com/id",
    headers={
        "Authorization": "access_token myToken"
    },
    cookies={},
)
tschmelz
  • 480
  • 1
  • 4
  • 10
3

I'll add a bit hint: it seems what you pass as the key value of a header depends on your authorization type, in my case that was PRIVATE-TOKEN

header = {'PRIVATE-TOKEN': 'my_token'}
response = requests.get(myUrl, headers=header)
Orkhan M.
  • 143
  • 1
  • 11
2

One of the option used in python to retrieve below:

import requests

token="abcd" < retrieved based>
headers = {'Authorization': "Bearer {}".format(token)}
response = requests.get(
    'https://<url api>',
    headers=headers,
    verify="root ca certificate"
)

print(response.content)

If you get hostname mismatch error then additional SANs need to be configured in the server with the hostnames.

Hope this helps.

skillsmuggler
  • 1,862
  • 1
  • 11
  • 16
rajeshk
  • 21
  • 1