Authentication & Rate Limits
Base URL
All requests use this base URL:
https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/CalHeatScore_Live_Data_for_API_Use/FeatureServer/0
Append /query and your query parameters to fetch heat score data:
https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query?where=1=1&outFields=*&returnGeometry=false&f=json
Authentication
No authentication is needed. The API is open and read-only — you cannot modify, create, or delete data.
| Requirement | Details |
|---|---|
| API key | Not required |
| OAuth token | Not required |
| Account | Not required |
| Access | Read-only (query operations only) |
Because no authentication is required, do not pass sensitive credentials in your requests. There is no need to include Authorization headers or token parameters.
Rate Limits
The CalHeatScore API is hosted on ArcGIS Online, which applies fair-use rate limits to public feature services. While specific thresholds are not published, follow these guidelines to avoid being throttled:
Per-request limits:
| Constraint | Value |
|---|---|
| Max records per response | 2,000 |
| Supported response formats | JSON, GeoJSON, PBF |
| Max concurrent requests | Not published — keep under 10 simultaneous requests |
Each record represents the data for one California ZIP code. Our dataset contains 1,721 ZIP codes.
Best practices to stay within limits:
- Request only the fields you need. Use
outFieldsto specify fields instead ofoutFields=*. This reduces response size and server load. - Disable geometry when you don't need it. Set
returnGeometry=falseif you only need attribute data. Polygon coordinates significantly increase response size. - Cache responses locally. Heat scores update once daily. Cache results and refresh once per day rather than querying on every page load.
- Paginate large requests. Use
resultRecordCountandresultOffsetinstead of requesting all records at once.
Response Formats
Set the f parameter to control the response format.
JSON (default)
Use f=json for standard JSON. Best for most application integrations.
curl "https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query?where=ZIP_CODE='90210'&outFields=ZIP_CODE,CHS_Day_0&returnGeometry=false&f=json"
import requests
BASE_URL = (
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/"
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query"
)
params = {
"where": "ZIP_CODE='95814'",
"outFields": "ZIP_CODE,CHS_Day_0",
"returnGeometry": "false",
"f": "json",
}
response = requests.get(BASE_URL, params=params)
data = response.json()
if "error" in data:
print(f"Error: {data['error']['message']}")
else:
for feature in data["features"]:
attrs = feature["attributes"]
print(f"ZIP {attrs['ZIP_CODE']}: score = {attrs['CHS_Day_0']}")
const baseUrl =
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/" +
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query";
const params = new URLSearchParams({
where: "ZIP_CODE='95814'",
outFields: "ZIP_CODE,CHS_Day_0",
returnGeometry: "false",
f: "json",
});
fetch(`${baseUrl}?${params}`)
.then((res) => res.json())
.then((data) => {
if (data.error) {
console.error(`Error: ${data.error.message}`);
return;
}
data.features.forEach((feature) => {
const attrs = feature.attributes;
console.log(`ZIP ${attrs.ZIP_CODE}: score = ${attrs.CHS_Day_0}`);
});
})
.catch((err) => console.error("Request failed:", err));
GeoJSON
Use f=geojson for GeoJSON. Best for mapping libraries like Leaflet, Mapbox, and D3.
curl "https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query?where=ZIP_CODE='95814'&outFields=ZIP_CODE,CHS_Day_0&outSR=4326&f=geojson"
import requests
BASE_URL = (
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/"
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query"
)
params = {
"where": "ZIP_CODE='95814'",
"outFields": "ZIP_CODE,CHS_Day_0",
"outSR": "4326",
"f": "geojson",
}
response = requests.get(BASE_URL, params=params)
geojson = response.json()
if "error" in geojson:
print(f"Error: {geojson['error']['message']}")
else:
for feature in geojson["features"]:
props = feature["properties"]
coords = feature["geometry"]["coordinates"][0][0]
print(f"ZIP {props['ZIP_CODE']}: score = {props['CHS_Day_0']}, first coord = {coords}")
const baseUrl =
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/" +
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query";
const params = new URLSearchParams({
where: "ZIP_CODE='95814'",
outFields: "ZIP_CODE,CHS_Day_0",
outSR: "4326",
f: "geojson",
});
fetch(`${baseUrl}?${params}`)
.then((res) => res.json())
.then((geojson) => {
if (geojson.error) {
console.error(`Error: ${geojson.error.message}`);
return;
}
geojson.features.forEach((feature) => {
const props = feature.properties;
console.log(`ZIP ${props.ZIP_CODE}: score = ${props.CHS_Day_0}`);
});
})
.catch((err) => console.error("Request failed:", err));
PBF (Protocol Buffers)
Use f=pbf for Protocol Buffers. Best for high-performance applications that need minimal response size. Requires a PBF decoder to parse the binary response.
curl "https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query?where=ZIP_CODE='95814'&outFields=ZIP_CODE,CHS_Day_0&returnGeometry=false&f=pbf" --output response.pbf
import requests
BASE_URL = (
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/"
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query"
)
params = {
"where": "ZIP_CODE='95814'",
"outFields": "ZIP_CODE,CHS_Day_0",
"returnGeometry": "false",
"f": "pbf",
}
response = requests.get(BASE_URL, params=params)
# Save binary PBF response to a file
with open("response.pbf", "wb") as f:
f.write(response.content)
print(f"Saved {len(response.content)} bytes to response.pbf")
const baseUrl =
"https://services1.arcgis.com/PCHfdHz4GlDNAhBb/arcgis/rest/services/" +
"CalHeatScore_Live_Data_for_API_Use/FeatureServer/0/query";
const params = new URLSearchParams({
where: "ZIP_CODE='95814'",
outFields: "ZIP_CODE,CHS_Day_0",
returnGeometry: "false",
f: "pbf",
});
// Node.js: save binary PBF response to a file
const fs = require("fs");
fetch(`${baseUrl}?${params}`)
.then((res) => res.arrayBuffer())
.then((buffer) => {
fs.writeFileSync("response.pbf", Buffer.from(buffer));
console.log(`Saved ${buffer.byteLength} bytes to response.pbf`);
})
.catch((err) => console.error("Request failed:", err));
Error Handling
The API returns errors as JSON objects with a code, message, and details array. Common errors:
| HTTP Status | Error Code | Cause | Fix |
|---|---|---|---|
| 200 (with error body) | 400 |
Invalid SQL in where clause |
Check your SQL syntax. String values need single quotes (ZIP_CODE='90210', not ZIP_CODE=90210) |
| 200 (with error body) | 400 |
Invalid field name in outFields |
Verify field names match exactly: ZIP_CODE, CHS_Day_0, etc. (case-sensitive) |
| 200 (with error body) | 500 |
Server error | Retry after a few seconds. If persistent, the service may be temporarily unavailable |
ArcGIS Feature Services return HTTP 200 even for errors — the error is in the response body. Always check for an error property in the JSON response before processing results.
{
"error": {
"code": 400,
"message": "Unable to complete operation.",
"details": [
"Invalid or unsupported SQL clause."
]
}
}