Skip to content

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:

  1. Request only the fields you need. Use outFields to specify fields instead of outFields=*. This reduces response size and server load.
  2. Disable geometry when you don't need it. Set returnGeometry=false if you only need attribute data. Polygon coordinates significantly increase response size.
  3. Cache responses locally. Heat scores update once daily. Cache results and refresh once per day rather than querying on every page load.
  4. Paginate large requests. Use resultRecordCount and resultOffset instead 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.

Example error response
{
  "error": {
    "code": 400,
    "message": "Unable to complete operation.",
    "details": [
      "Invalid or unsupported SQL clause."
    ]
  }
}