Getting data from Census Data API is not working

629 Views Asked by At

I am trying to get data form Census Track data in Anaconda and jupyter-nootbook using Pandas, but I am keep getting error. My code:

import pandas as pd
import numpy as np
import requests
import geopandas as gpd

year = '2021'
variable = 'B09019_003E'
with open (r"pathToKeyFile/census_api.txt", "r") as f:
    c = f.read();

url='https://api.census.gov/data/{0}/acs/acs5?get=NAME,{1}&for=tract:*&in=state:12%20county:057&key={2}'\
    .format(year, variable, c)
response = requests.request("GET",url)

response.raise_for_status()

print(response.json)

temp = pd.DataFrame(response.json()[1:], columns=response.json()[0])

'print(response.json)' output:

b'\n<html>\n    <head>\n        <title>Invalid Key</title>\n    </head>\n    <body>\n        <p>\n            A valid <em>key</em> must be included with each data API request.\n            You included a key with this request, however, it is not valid.\n            Please check your key and try again.\n        </p>\n        <p>\n            If you do not have a key you may sign up for one <a href="key_signup.html">here</a>.\n        </p>\n    </body>\n</html>\n'

My census_api.txt only contains the key. This is the error when running pd.DataFrame()

SONDecodeError                           Traceback (most recent call last)
File C:\ProgramData\anaconda3\lib\site-packages\requests\models.py:971, in Response.json(self, **kwargs)
    970 try:
--> 971     return complexjson.loads(self.text, **kwargs)
    972 except JSONDecodeError as e:
    973     # Catch JSON-related errors and raise as requests.JSONDecodeError
    974     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError

File C:\ProgramData\anaconda3\lib\json\__init__.py:346, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    343 if (cls is None and object_hook is None and
    344         parse_int is None and parse_float is None and
    345         parse_constant is None and object_pairs_hook is None and not kw):
--> 346     return _default_decoder.decode(s)
    347 if cls is None:

File C:\ProgramData\anaconda3\lib\json\decoder.py:337, in JSONDecoder.decode(self, s, _w)
    333 """Return the Python representation of ``s`` (a ``str`` instance
    334 containing a JSON document).
    335 
    336 """
--> 337 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    338 end = _w(s, end).end()

File C:\ProgramData\anaconda3\lib\json\decoder.py:355, in JSONDecoder.raw_decode(self, s, idx)
    354 except StopIteration as err:
--> 355     raise JSONDecodeError("Expecting value", s, err.value) from None
    356 return obj, end

JSONDecodeError: Expecting value: line 2 column 1 (char 1)

During handling of the above exception, another exception occurred:

JSONDecodeError                           Traceback (most recent call last)
Cell In[21], line 1
----> 1 temp = pd.DataFrame(response.json()[1:], columns=response.json()[0])
      2 temp['state'] = temp['state'].astype('str')
      3 temp['county'] = temp['county'].astype('str')

File C:\ProgramData\anaconda3\lib\site-packages\requests\models.py:975, in Response.json(self, **kwargs)
    971     return complexjson.loads(self.text, **kwargs)
    972 except JSONDecodeError as e:
    973     # Catch JSON-related errors and raise as requests.JSONDecodeError
    974     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
--> 975     raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

JSONDecodeError: Expecting value: line 2 column 1 (char 1)

When I open the URL itself it is saying that my API key is invalid, while I am sure it is fine and I have just got that. Any thought on this?!

2

There are 2 best solutions below

0
user21807639 On BEST ANSWER

If you have just received your API key, and activated it, then you have to wait longer for it to actually activate. I checked back within a day and my code began working.

The api will return a 200 OK and give that exact message. Give it some time. It will work.

2
webelo On

This is not an issue with the census API per se. The error posted comes from the fact that the response is not valid JSON. This is not a problem for the API unless it advertises that it returns JSON in all cases.

Notice that requests.Response#json requires that the response text is valid JSON. You can use requests.Response#text if the response is text or even requests.Response#content for bytes.

After making your request, call response.raise_for_status() in order to raise any errors (403, 404, etc.).

Once you know that the response is OK, try printing the response to see its form. It may not be a JSON. It may be rectangular, etc.

import requests

year = '2021'
variable = 'B09019_003E'
with open (r"pathToKeyFile/census_api.txt", "r") as f:
    c = f.read();

url='https://api.census.gov/data/{0}/acs/acs5?get=NAME,{1}&for=tract:*&in=state:12%20county:057&key={2}'\
    .format(year, variable, c)
response = requests.request("GET",url)

response.raise_for_status() # Check for any errors

print(response.content) # Preview the output (or just save it so you can refer to it later)

If you'd like to update your question with the response content, we can look into getting it into a frame.

Edit: Update to reflect new info

The response you provided indicates that your key is invalid. Here is the rendered HTML for the response:

enter image description here

I'm not seeing anything in the census documentation to indicate that error messages will be valid JSON (even if the response for a 200 is valid JSON).