AQI location bound list of sensors limited?


I’m trying to pull a list of sensors within a given lat/lon bounding box (Puget Sound, to be specific), and while the code (Python) runs fine and I’m getting a 200 response with data from the server, the list is suspiciously small.

There’s no way that there are only 36 sensors within Puget Sound that have pm2.5 data. Is there any way I can get a complete list of sensor_index for the given lat/lon box? I’ve tested this both in the code below and in the API documentation, and the result is the same (36 stations).

url string of the request:

code sample:

import requests
import json
import pandas as pd

with open('api_key.txt') as f:
    api =

headers= {'X-API-Key': api}

# get list of sensors within lat/long bounding box (defined by NW/SE corners)

# Port Townsend City Hall
NWlng = 48.1162201
NWlat = -122.755863

# Peak of Mt. Rainier
SElng = 46.8555182
SElat = -121.7631845

url = '' + str(NWlng) + '&nwlat='+ str(NWlat) + '&selng=' + str(SElng) + '&selat=' + str(SElat)

response = requests.get(url, headers=headers)
print("Status Code: ", response.status_code)

content = json.loads(response.content)
data = content["data"]
columns = content["fields"]

df = pd.DataFrame(data, columns=columns)


Status Code:  200
(36, 2)

Additional two points just discovered!

1 - apparently I needed to set max_age=0 and modified_since=0 to not filter out too many (now n=300)
2 - The sensors I’m getting in this list don’t make any sense, as apparently I’m setting the bounding box incorrectly somehow? (This also happens in the API Docs tester).

See screenshot below that has both the lat/lon bounding box and the results. For example: “Downtown New Orleans” is certainly not located in Puget Sound.

Well, I can say it’s not just you. I tried this with your coordinates as well as a smaller area (just a few square miles around my home in Kirkland, WA) with no better results.

If you look at the Purple Air map centered over the Puget Sound area, you’ll see that there are lots of available sensors. (Real-Time Air Quality Map | PurpleAir)

But what I noticed in the results from your call is that the latitude and longitude for all of the stations returned are null. With null coordinate values there’s no way to place them on a map.

It seems like this must be an issue with the API. It should be ignoring all stations with null latitude and/or longitude values, but it’s instead returning only stations with null coordinate values.

For my own use, I picked a bunch of stations near me using the map page (Real-Time Air Quality Map | PurpleAir) to get the sensor_index value. All of the stations I picked (like 34585 and 76973) have valid coordinate values - otherwise they wouldn’t be on the map. (As an aside, I created a group containing all of the sensors I wanted, and then I use the Get Member Data API call to get the data for those stations. This method, though, might not work for you if you’re looking for “all” of the stations in the Puget Sound area rather than picking them manually.)

I’ll leave it to you to contact Purple Air and report the issue with the coordinates search.

Thanks for confirming that I’m not crazy!

In regards to the null values for latitude and longitude, @jeffgo is correct. These are, in fact, sensors that do not have a location set and are thus located in what we refer to as “No Man’s Land,” which you can see down near Antarctica on our map.

The reason your request isn’t returning data for the sensors you want is that your latitude and longitude are backwards. Flip those and you should be good to go!

1 Like


Well, that’s a fantastically dumb mistake. Thanks for the catch and not just pointing and laughing.

1 Like

I now have a big red sore spot on my forehead from slapping it. At least I got the part about the null coordinate values right! :face_with_spiral_eyes:

1 Like

Actually, a very easy mistake to make, considering that we put longitude before latitude in our documentation, which is backwards for most people.

I’m attempting my first API call to get sensor_index from a bounding box. However, the sample call returns no data (unlike the example screenshots in this thread which show data). I’m having the same problem when I put in R. Can someone point me in the right direction? Here’s my query from the sample call:

That’s a gigantic geographic area. Maybe test on a smaller square?

Another idea: it might be getting confused by you crossing 180 degrees of longitude. You want a square covering most of the pacific and N America, not one covering most of Eurasia and the Atlantic, right?

So a workaround would be to cut into two chunks, the part to the East of 180 degrees and the part to the West, then merge the data.

That did it! I think I just had the wrong nwlng to begin with. Thank you!

1 Like

the returned locations of the sensors are way different than the passed boundary locations. I tried nwlng=-121.75,nwlat= 37.42, selng= -114.52, selat=32.55. When I checked the locations of the returned sensors I got selected_sensors[‘latitude’].max(), selected_sensors[‘latitude’].min() = (62.34708, -40.87172). How is this possible? Can you please help?

We responded to your comment in this thread. Try providing us the URL you used for your API request and we can examine it.

What Josh_PurpleAir said. I’d be happy to help, just need to see your query so I can unpack it.