Map Addresses for Free with the Census Geocoding API

Looking for a free geocoding solution and frustrated by the lack of options?

Though it’s poorly publicized (and documented), the US Census Bureau maintains a RESTful API for real-time and batch geocoding that’s free, fast, and accurate. It doesn’t even require an API key. Essentially, it’s everything you’d get out of a roll-your-own PostGIS Census/TIGER solution, without the hassle of having to set it up.


Buildings are related to Geocoding, right?
Image Credit: Diego Delso [CC BY-SA 3.0], via Wikimedia Commons

The only limitation is that the API mainly provides geocoding for residential addresses. Because the Census Bureau’s primary task is, well, conducting the national census, they’re a lot more interested in where people live than where they work. So, if you need to map business addresses, you may have to go elsewhere. But if you’re mapping customers (or students, or volunteers, or mailing list recipients, or whatever), the service is pretty on-point. In my work, I’ve seen about a 90% match rate for customer addresses when submitted to Census. Not too shabby.

Making Requests

So, how do you hit the API? Well, it would be good to start by reading the documentation, even though it’s a bit lacking. You’ll get a high-level overview of what’s possible, including features I won’t talk about in this post.

The API has several different endpoints. Endpoints depend, first, on whether you want to code a single address or a batch of up to 1000. They also depend on whether you want to get only lat/longs, or if you also want Census geography information (e.g., what census block the address is in). For this guide, we’ll assume you just want to get the lat/long.

When making requests, you’ll also want to specify the “benchmark” to query. This is essentially what year of data you want to use for your mapping. We’ll be using the “Public_AR_Current” benchmark, which is the most up-to-date information, but there are some situations where it might make sense to use an outdated benchmark to code old addresses. Do what makes sense.

Hitting the endpoint for a single address is pretty easy. Simply use query string parameters to specify address parts (you can do one-line address as well), benchmark, and output format. That’s all there is to it!

Here’s how to code a single address using PHP and cURL.

And here’s the output!

Every once in a while, you may get more than one match. In my experience, the matches are usually close enough together to be virtually equivalent for most purposes, but your mileage may vary.

Batch Requests

Of course, if you need to code, say, 800,000 addresses, going one at a time would be silly. Thankfully, there’s also an endpoint for batch geocoding. You simply fire off a POST request, specifying the benchmark and uploading a CSV file of up to 1000 addresses. The CSV file should simply include unique ID (you’ll get the results in a random order), street, city, state, and zip.

We’ll use this for a test CSV.

And here’s some code for mapping a file of addresses, again using PHP and cURL.

And the output.

Note that the output includes the unique ID we supplied, the supplied address, whether there was a match, the match type, the matched address, the lat long, the street ID number, and whether the address is on the left or right of the street.

Though it’s not specified in the documentation, there’s two things to note here. First, you’ll only get one match per address – presumably, the best. Second, “exact” matches are those where everything in the address lines up perfectly with the Census data. A “non-exact” match means that something was off… for example, the zip code you supplied doesn’t match the zip code in their data, even though everything else is lining up. In my experience, “non-exact” matches are still very reliable.

Of course, if you wanted to geocode more than 1000 addresses, you’d need to chunk them into batches of 1000 and submit each batch separately. I’ll let you write your own code for that… it’s pretty straightforward.


The Census geocoding API isn’t perfect, especially if you need to map mostly non-residential addresses. But it’s one of the best free tools out there. I’ve been making pretty regular use of it in my work, and I’ve been consistently impressed by the speed and accuracy… not to mention the price.

9 Responses

  1. Daniel Y May 12, 2016 / 12:12 pm

    Thanks for the article Dayne. If you are using for work how do you mitigate when the lookup goes does? I’m trying to script something for a “” lookup and am getting internal server errors. Even with the sample URL supplied by the census.

    • daynebatten May 12, 2016 / 12:44 pm

      Hey Daniel,

      We’re using the Census geocoder for a daily load of data into a data warehouse in a business analytics context. If the job breaks for the day, we simply re-load the data later. I understand in some production contexts (e.g., an application that needs to geocode addresses on demand) that may not be acceptable…

  2. Bryan July 13, 2016 / 8:24 pm

    Hi Dayne – Good stuff, thanks for writing it up. Have you figured out what the rate limits are for the batch API? I’ve been looking into a bit and haven’t been able to find any information.

    • daynebatten July 19, 2016 / 8:57 pm

      Good question. I don’t seem to remember there being any limits… and I may have even contacted Census to ask. It’s been a while now. When I get into work tomorrow, I’ll see if I can dig up any old emails or code that might shed some light on the issue.

      • Taylor March 30, 2017 / 8:44 pm

        A colleague mentioned that he got banned after making 9 batch requests in 9 minutes. I just fired off an email to them so we’ll see what they say.

        • daynebatten March 31, 2017 / 8:24 am

          Yeah, it wouldn’t surprise me if they implemented rate limits since I wrote this post. In my office, we actually switched to using the Google Maps Geocoding API, because the Census geocoder was down for a week or so straight. I wouldn’t be surprised if it went down under load and they had to implement some rate limits.

          Also, Google Maps changed their policy to allow you to geocode for any purpose (it used to be that you could only do it for the purposes of a web app that used Google Maps).

  3. Jack August 8, 2016 / 11:26 am

    Thanks a bunch Dayne! I converted some of this logic to a .net project and it is working out great! What a great option for geocoding large batches of addresses. Couldn’t find anything close to comparable that is free.

  4. Kory Skistad January 24, 2017 / 11:07 am

    Hi Dayne,

    I’m trying to find examples of how to submit batch addresses without using cURL. All of the examples I’ve seen so far use this. Isn’t there a native way in .NET to accomplish the same thing without this 3rd-party library?

Leave a Reply

Your email address will not be published. Required fields are marked *