Python authentication - 401 no matter what I try

Hi there,

I’ve been banging my head against this one for 2 days now and I just can’t find the right syntax. I’ve connected to CH APIs before but using PHP, this time I’m trying to write a Python script and I’m falling at the first hurdle - authentication. Here’s my very simple code:

url = f"https://api.company-information.service.gov.uk/company/{company_number}"
keyEncoded = base64.b64encode(api_key.encode('utf-8'))
response = requests.get(url, auth=(keyEncoded,''))

This is just the current version - I’ve tried without encoding the API key, I’ve tried with and without : at the end of the API key, I’ve tried using Python’s HTTPBasicAuth, I’ve tried adding a header with auth in it… Every time, I get a 401 error - which suggests the problem is not with the key itself (and indeed, I’ve tested it in my PHP code and the key is fine) but the way in which I’m using it.

The code above is based on another post I found here on the forum, but it was a couple of years old. I’m sure I’m one iteration away from trying the right combo of encoding, colon, and auth method but I just can’t find it. Please help!

I’m not a Python coder but looking at your code snippet above you’re encoding the API key and then passing it to Python’s requests.get. However the Python docs seem to suggest - for http Basic - that you should pass the raw username and password (e.g. in this case the API key and ‘’).

I’m not entirely sure why you’d need api_key.encode('utf-8') - and that’s an extra step here (but again I don’t know Python). I am also assuming that Companies House generally provide ASCII-only API-keys. If so then your API key should already be valid UTF-8.

If you were manually doing this with Python e.g. making your own “Authorization” http header you would need to base64 encode the API key and a final “:” and then supply that as the Python headers parameter.

If you needed to check things further it might be a good idea for you to check exactly what you’re sending. The Python docs say you can inspect your request, which should help you debugging. So for example you could make the request using curl with verbose mode (so showing the headers you’re sending) and also check what Python’s API says it’s sending and compare the two.

Good luck.

Thanks voracity - I didn’t know I could inspect the request, thanks for that. I’ve taken a look at what I’m sending and it looks OK to me - the URL is correct, the authorization is sending correctly for Basic HTTP (I’ve ditched the base64 encoding). If I had copied/pasted the API key incorrectly I’d expect to get a 403 response (although maybe not). Here’s the inspected request I’m sending:

GET request failed with status code:  401

{'method': 'GET', 'url': 'https://api.company-information.service.gov.uk/company/08436708', 'headers': {'User-Agent': 'python-requests/2.25.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic MTU5N<snip>DczOg=='}, '_cookies': <RequestsCookieJar[]>, 'body': None, 'hooks': {'response': []}, '_body_position': None}

I’ve shortened the authorization string for security. Does anything look out of place?

Thanks!

Never mind… it’s a long story but I had been using an invalid key. I’d tested initially with a valid key but the code was wrong - then started using an invalid key so whether the code was right or wrong it never worked. Went back to my initial key and, with changes informed by voracity, I got it working. For Python users of the future my code ended up being:

url = f"https://api.company-information.service.gov.uk/company/{company_number}"    
response = requests.get(url, auth=(api_key,''))
2 Likes