Environmental Justice Community Reports

How to pull reports and data from EIP's EJAM API

When EPA took the EJSCREEN website and its API offline in February 2025, communities and researchers lost an easy way to pull environmental justice indicators for a neighborhood, county, or custom area. This tool fills that gap. It's built on EJAM, an open-source project that recreates EJSCREEN's report-generating features, and it's reachable through one address, or "base URL":

http://138.197.109.76:8181

You can use it two ways, and this guide covers both:

There's also a built-in documentation page, generated automatically by the tool itself, if you ever want to double check something or see it laid out a different way:

http://138.197.109.76:8181/

Note: Report and data requests are processed on EIP’s Digital Ocean server, so how fast a report comes back can vary with how much memory and storage is available at that moment. Small single-site reports are usually quick. Large multi-site reports covering many points or big polygons, or requests made when the server is busy, can take longer. If a request is taking a long time, it is often still working. It may just need a minute.

Using it in your browser

The simplest way to use this tool is to build a web address (a URL) that tells the API what you want, and paste that address into your browser like you would to access any website. After a loading period, a report will open or download.


Basic Pattern

Every request starts with our base address, followed by /report and then a list of filters after a question mark. Filters are separated by an ampersand (&). For example, this asks for a report on one county, identified by its FIPS code (a standard Census code for a state, county, or other area):

http://138.197.109.76:8181/report?fips=10001

This asks for a report on the area within 1 mile of a specific point (given as latitude and longitude), in downtown Phoenix:

http://138.197.109.76:8181/report?lat=33.45&lon=-112.07&buffer=1

This asks for one combined report covering two counties at once (note sitenumber=0, which tells it to summarize the sites together rather than reporting on just one):

http://138.197.109.76:8181/report?fips=10001,10003&sitenumber=0&fileextension=html

Getting a FIPS code or coordinates

A FIPS code identifies a state or county (for example, 10001 is New Castle County, Delaware). You can look one up on the U.S. Census Bureau's website, or search "FIPS code for [county name]" in any search engine. Latitude and longitude for an address can be found by searching the address on Google Maps, right-clicking the pin, and copying the coordinates that appear.

Building your own link

You don't need all the pieces below — just fill in what applies to your situation. Start from the base address, add /report?, and then combine any of these, separated by &:

Instruction What it does
lat / lon The latitude and longitude of a point you care about. You can list more than one, separated by commas, as long as the list order matches for both.
fips A Census FIPS code (state, county, etc.). You can list several separated by commas.
buffer How far out from your point (in miles) to include in the analysis. Defaults to 3 miles for a point. Set buffer=0 for no extra radius.
sitenumber Which location to report on, if you gave more than one. Use sitenumber=0 for a combined summary of all locations together. Leave it out for a single location.
fileextension pdf or html. If you leave this out, one location gives you a PDF; multiple locations (sitenumber=0) give you an interactive HTML page.

Example

You want to check on the area within 2 miles of a specific address. First, find the latitude and longitude of that address using Google Maps (right-click the pin, click the coordinates to copy them). Suppose that gives you 39.95, -75.16. Your link would be:

http://138.197.109.76:8181/report?lat=39.95&lon=-75.16&buffer=2

Paste that into your browser and a PDF report will download automatically, covering the population and environmental indicators within 2 miles of that point.

What you'll get back

Using it from code

If you're incorporating this into a script, dashboard, or automated pipeline, the tool works the same way under the hood — you're just sending the request programmatically instead of typing it into a browser. There are two main endpoints you'll use: /report (for the same PDF/HTML reports described above) and /data (for raw numbers back as JSON, ready to load into a spreadsheet or dataframe).

Getting a report from a script

A simple GET request works exactly like the browser links above. In Python:

import requests
url = "http://138.197.109.76:8181/report"
params = {"fips": "10001"}
response = requests.get(url, params=params)
with open("county_report.pdf", "wb") as f:
f.write(response.content)

For a very large number of locations, or a complicated polygon that's too long to fit in a web address, send the same information as a POST request instead. This example asks for a combined HTML report covering several hand-drawn areas (as GeoJSON):

import json, requests
payload = {"shape": json.dumps(feature_collection),"buffer": 0, "sitenumber": 0, "fileextension": "html"}
response = requests.post("http://138.197.109.76:8181/report", json=payload)
html = response.text

Getting raw data instead of a report

If you want the underlying numbers rather than a formatted report — for example, to build your own chart or combine results with other data — use /data. This always uses a POST request. A few examples:

import requests, pandas as pd
url = "http://138.197.109.76:8181/data"
# A single point, 4-mile radius
payload = {"buffer": 4, "sites": [{"lat": 33, "lon": -112}]}
# Several blockgroups by FIPS code
payload = {"buffer": 0, "fips": ["482012301001", "482012302002"], "scale": "blockgroup"}
# An entire state, at the county level
payload = {"buffer": 0, "fips": "DE", "scale": "county"}
response = requests.post(url, json=payload)
data = response.json()
df = pd.DataFrame.from_dict(data)

Handing results off to the full EJAM app

If you'd rather let someone explore results interactively in the full EJAM web app instead of generating a report yourself, you can "hand off" a set of locations to it. First, send the locations to /handoff, which hands back a short-lived token:

payload = {"sites": [{"lat": 33, "lon": -112}], "radius": 3}
response = requests.post("http://138.197.109.76:8181/handoff", json=payload)
token = response.json()["token"]

Then open the EJAM app with that token attached to the address (for example, appending ?handoff= to the EJAM app's URL). The app will load with those locations already selected. Tokens expire after about an hour, so generate one only when you're ready to use it.

Quick reference: /data parameters

Parameter What it does
sites A list of latitude/longitude pairs, e.g. [{"lat":33,"lon":-112}]
shape A GeoJSON object describing a custom area (as a JSON string)
fips One or more FIPS codes
buffer Miles to extend the search around a point or polygon edge. Default=0
scale For FIPS requests, whether to summarize at the county or blockgroup level
geometries Set to true to also return the shape of each area analyzed. Default=false

A few closing tips