I have a bunch of latitude,longitude coordinates (mostly city/town centroids) in the United States for which I'd like to find the containing census tract.

For instance,

input => nn.nnn, -nn.nnn 
output => 010300

Is there a free or low-cost API out there that can help? (Essentially Yahoo Placefinder, with the additional response of census tract.)

(I understand that many cities include multiple census tracts and I'd expect that some small towns contain only parts of one or more census tracts. I'm comfortable ignoring that issue for now.)

  • Are you thinking about solution for a certain area or country agnostic solution? – radek Mar 10 '12 at 1:04

The FCC census block conversion API is exactly what you're looking for.

| improve this answer | |
  • Yup. Embarrassing, because I considered it for another part of the project, and had forgotten. Thanks. – Citizentools Mar 15 '12 at 3:23
  • Note, in 2018 that link shows "This API has been replaced by the new Area and Census Block API, updated to reduce response time and support additional Area related data elements. As such, this legacy API is being decommissioned." and links to geo.fcc.gov/api/census. Commenting for posterity – arvi1000 Jun 20 '18 at 22:29

In PostGIS, if you have a table of points, and the census boundary information that @Sminbamangu refers to you could calculate this using the following approach:

       census_boundary as c,
       table_of_points as p
       ST_Contains(c.geom, p.geom);

You can see the description ST_Contains here. This would return a table of the points, and the census tract where they are located.

| improve this answer | |
  • Tried that in Spatialite with 10 points and the California data and it does it in about 0.2 seconds ... +1. – Simbamangu Mar 11 '12 at 6:33
  • Nice - I must explore Spatialite. I started using PostGIS 6 months ago and love it, but it's pretty heavy duty. Would be nice to have more self-contained datasets that are portable for times when there is no internet. – djq Mar 11 '12 at 15:45

You could do it locally instead of an online API. One solution with R: Census boundary data for the USA is available through TIGER at census.gov; if you're thinking about the US then you could download the US states and use a function to get the tracts. For example, using California and a random (or random-ish) point:


tractLookup <- function(x, y, state) {
  pt <- SpatialPoints(data.frame(x = x, y = y))
  overlay.pt <- overlay(pt, state) # what index number does pt fall inside?
  return(census$TRACT[overlay.pt]) # give the Tract number from the census layer

Try it out:

california <- readShapePoly("~/Downloads/US_2000_Census_Tracts/tr06_d00_shp/tr06_d00.shp")
tractLookup(-123.123, 40.789, california)

Gives 0004, which is correct.

# Look at the map
map('state', c('California'), lwd = 2, col = 'green', add = F) # optional
points(-123.123, 40.789, col = 'red', lwd = 2)

This works, but takes 5 seconds on my Mac, which would probably be too much if you're going to do a lot of this; I suspect someone will weigh in shortly with a PostGIS solution that will be a million times quicker ...

| improve this answer | |

As mentioned by @Simbamangu, this could easily done locally by just about any desktop GIS software on the market.

For free & open source, take a look at a "join attributes by location" in QGIS.

If you plan to need to do this repeatedly over time, you could consider putting the datasets into PostGIS and creating a spatial join (see this example in the online help). You can then visualize the results in QGIS.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.