Project Sidewalk

Welcome back

Project Sidewalk

Join Project Sidewalk

Map sidewalks. Help make your city accessible to everyone.

3–30 characters — letters, numbers, hyphens, and underscores

Pick a nickname — you don't have to use your real name. It's shown publicly on the leaderboard and your profile, and you can change it anytime.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number
Passwords match

AccessScore: Streets API

The AccessScore: Streets API returns an accessibility score in the range (0, 1) for each street — higher is more accessible. A street's score combines three things: its own segment, scored from the obstacles, surface problems, and missing sidewalks along it, and the intersections at its two ends, scored from the curb ramps, crosswalks, and signals pooled at each corner (see the AccessScore: Intersections API). Each piece weights every clustered feature by its type, its severity/quality rating, and its tags, then squashes the total with a logistic function.

AccessScore extends the method introduced in Li et al., A Pilot Study of Sidewalk Equity in Seattle (Urban Access 2022). It is experimental: the weights are deliberately simple and subject to change. For full control you can compute your own index from the Label Clusters API.

AccessScore: Streets Preview

Below is a live preview of street AccessScores from a sample region in Walla Walla, WA, retrieved directly from the API. Streets are colored from red (low accessibility) to green (high); gray streets have not yet been audited. Hover or click a street to see its score and the accessibility features that produced it.

One method, not the method. There is no single correct way to measure street-level accessibility—researchers and practitioners use many different approaches. AccessScore implements just one such algorithm, and it is experimental: the weighting is deliberately simple and subject to change. Treat these scores as one lens rather than a definitive measure, and compute your own index from the Label Clusters API if a different method suits your needs better.

Endpoint

Returns a street segment and its AccessScore for each street in the queried area, optionally filtered by the Query Parameters below.

GET /v3/api/accessScoreStreets

Examples

/v3/api/accessScoreStreets?filetype=geojson Get AccessScores for all streets in GeoJSON (default)

/v3/api/accessScoreStreets?filetype=geojson&inline=true Same, but opened in the browser

/v3/api/accessScoreStreets?filetype=csv Get AccessScores for all streets in CSV

/v3/api/accessScoreStreets?regionId=8 Get scores for streets in a single region

How the score is computed

Project Sidewalk clusters proximal labels of the same type, and scores two kinds of unit from them: a street's segment and an intersection. Four of the seven scored label types are corner features — CurbRamp, NoCurbRamp, Crosswalk, Signal — so each of their clusters is attributed to the nearest intersection within 25 m (on whichever street it sits) and scores that intersection, pooled with the corner features of every other street meeting there. The rest of the street's clusters score its segment: the along-length types (Obstacle, SurfaceProblem, NoSidewalk), plus any corner-type cluster too far from an intersection to belong to one (a mid-block crosswalk and the curb ramps serving it), which counts as an ordinary point feature.

A street's headline score is the plain mean of its segment_score and the scores of its start and end intersections, over whichever of the three exist — a trip along a street includes getting on and off it. An end with no intersection (a dead end, a street split at a region boundary) or a grade-separated one contributes nothing, and an unaudited street between two scored crossings still gets a headline from them. All three components are reported, so you can recombine them your own way.

Scoring a segment. Each scored label type contributes a signed term; the segment's score is the logistic (sigmoid) of the sum of those terms, mapped to (0, 1). An audited street with nothing on it scores the neutral 0.5.

Most types are scored per cluster. Each cluster contributes base(type) × ratingMultiplier + Σ tagAdjustments, and the type's term is the sum over its clusters on the street:

  • Positive, quality-rated (CurbRamp, Crosswalk): rated Good / Okay / Bad → multiplier +1.0 / +0.5 / −1.0. A Bad feature therefore lowers the score.
  • Negative, severity-rated (NoCurbRamp, Obstacle, SurfaceProblem): rated Low / Medium / High → magnitude 0.33 / 0.67 / 1.0 of the (negative) base.
  • Presence-only (Signal): no rating; each cluster adds the base weight as-is.
  • Tags adjust a cluster's weight when present on at least half of its labels — e.g. a Signal tagged hard to reach buttons counts negatively, while APS (accessible signal) counts positively.
  • Length normalization (Obstacle, SurfaceProblem): these describe problems along a street, so their terms are scaled to a density per 100 m — term × 100 / max(length_meters, 25). Three obstacles on a 300 m street score as one on a 100 m street; a long street is not penalized for having more room for problems. The 25 m floor keeps a stub of a street from multiplying one problem without bound, so the factor never exceeds 4.

NoSidewalk is scored once per street, as a street condition, rather than per cluster. A missing sidewalk is a stretch, not a point: labelers pin it repeatedly along the street and it is clustered at 10 m, so a per-cluster weight would measure how many pins were dropped instead of whether the street has a sidewalk. All of a street's NoSidewalk clusters pool into a single term, which is what score_no_sidewalk reports:

score_no_sidewalk = base × min(1, n / 3) + Σ tagAdjustments
  • n is the street's NoSidewalk cluster count (n_no_sidewalk). The extent factor min(1, n / 3) saturates at 3 clusters: one stray pin counts 1 / 3 of the base weight, and 3 or more count the full weight however many more there are.
  • Known limitation. A cluster count is a proxy for coverage, and NoSidewalk clusters at 10 m, so how readily a street reaches 3 clusters depends on how long it is. A very short street without a sidewalk can be structurally unable to saturate, and so scores somewhat higher than a long street in the same condition. Pooling removes this effect above saturation but not below it.
  • Street-wide tags are judged over the street's pooled NoSidewalk labels: a tag adjusts the term when at least half of those labels carry it. street has no sidewalks and street has a sidewalk (the other side of the street has one) are mutually exclusive, so at most one is active unless the labels split exactly in half, in which case they cancel.
  • ends abruptly marks the point where a sidewalk stops, so it is active when any single cluster carries it on at least half of that cluster's labels. It aggravates the score: a pedestrian on the sidewalk is stranded in the roadway where it ends.
  • Worked example (current weights, before the street's other features): a street with eight NoSidewalk clusters and no tags scores sigmoid(-2.00) ≈ 0.12; tagged street has no sidewalks it drops to sigmoid(-3.00) ≈ 0.05; tagged street has a sidewalk it rises to sigmoid(-1.00) ≈ 0.27. A single NoSidewalk cluster with no tags is sigmoid(-0.67) ≈ 0.34.

The base weights and tag adjustments below are read directly from the scoring engine, so they always match what the API computes:

Label typeBase weightRatingTag adjustments
CurbRamp +0.75 Quality (Good / Okay / Bad)
missing tactile warning -0.25
narrow -0.25
points into traffic -0.25
steep -0.25
NoCurbRamp -1.00 Severity (Low / Medium / High)
alternate route present +0.25
no alternate route -0.50
Obstacle -1.00 Severity (Low / Medium / High) —
SurfaceProblem -1.00 Severity (Low / Medium / High) —
Crosswalk +0.75 Quality (Good / Okay / Bad)
level with sidewalk +0.25
no pedestrian priority -0.25
paint fading -0.25
Signal +0.50 Presence only, per cluster
APS +0.25
button waist height +0.15
hard to reach buttons -0.25
NoSidewalk -2.00 Street condition: one pooled term per street
covered walkway +0.50
ends abruptly -1.00
gravel/dirt road -0.25
pedestrian lane marking +0.50
shared pedestrian/car space +0.25
street has a sidewalk +1.00
street has no sidewalks -1.00

The per-type cluster_counts and sub_scores in each response let you see exactly how a street's segment was composed: the sub_scores sum to logit(segment_score). A corner type appearing there is a mid-block cluster; the ones at the corners are on the intersections. Other label types (Occlusion, Other) do not affect the score.

Note: Region scores (see the AccessScore: Regions API) are the length-weighted mean of their streets' headline scores, alongside a plain mean of their intersections.

Recomputing the score under your own weights

Every street carries the inputs to its score, so you can re-weight it yourself. GET /v3/api/accessScoreConfig returns the engine's configuration — the scored types in order, each type's base weight and scoring mode, the rating multipliers per bucket, the tag adjustments, the street-condition saturation count, and a few named weight presets — as JSON:

GET /v3/api/accessScoreConfig

Then, per street, each type's segment term is rebuilt from severity_counts, tag_adjustments, and length_meters:

  • Per-cluster types (positive_quality, negative_severity, presence_only): term = weight × Σbucket severity_counts[type][bucket] × multiplier(bucket) + tag_adjustments[type], where the multiplier comes from quality_multiplier or severity_multiplier by scoring mode, and is 1 for presence_only.
  • Street-condition types (street_condition): term = weight × min(1, n / street_condition_saturation_count) + tag_adjustments[type], with n the type's total cluster count.
  • Length-normalized types (length_normalized is true): multiply the whole term by length_normalization.per_meters / max(length_meters, length_normalization.min_length_meters).
  • segment_score = sigmoid(Σtype term + grade_term). With the engine's own base_weight for every weight, the terms equal sub_scores and, with the street's published grade_term, the result equals segment_score. To score the labels alone, drop the grade_term.
  • An intersection is rebuilt the same way from its own severity_counts and tag_adjustments, with no length factor; the street's headline score is then the mean of segment_score and the scores of start_intersection_id and end_intersection_id, over those that are not null.

Its grade object is what reads the grade fields: the two limits (walking_surface_limit, ramp_limit), the grades a map of them is classed at (map_class_breaks), and under sources the credit for each elevation model this city's streets were sampled from, with how many streets each covers.

The grade_scoring object publishes the settings the served scores were computed under, as defaults: a weight of 1.0 on max_grade, ramping between the two limits. That is the grade_term each street carries. To apply settings of your own, recompute the term and put it in that one's place in the sum above, grade_term = −weight × units:

  • Which streets take part. A street with no grade at all (a bridge, a gap, an unsampled street) takes no grade term. Neither does one whose grade is approximate, meaning grade_confidence is "low" or grade_quality is "suspect" (both are a straight line between the street's ends), unless include_approximate is set. The same gate applies to the barrier.
  • mean_grade and max_grade statistics: units = clamp((grade − low_threshold) / (high_threshold − low_threshold), 0, 1), where grade is that field, or |net_grade| on any street where the field is null and net_grade is not. If high_threshold ≤ low_threshold there is no ramp between them and units is a step: 1 when grade > low_threshold, else 0.
  • meters_over_limit statistic: units = clamp((meters_over_5pct + meters_over_8pct) / (2 × length_meters), 0, 1), with a null length counted as 0. The thresholds do not move it: those lengths were measured against the two fixed limits when the street was sampled.
  • Barrier: with barrier_enabled, a street whose max_grade (or |net_grade| where that is null) is greater than barrier_threshold has a segment_score of 0 outright. Its headline score still averages that 0 with its end intersections.

statistics lists the statistic ids, and weight_range and threshold_range what a control may sensibly offer. An unaudited street has a grade and still has no score.

The response also carries clusters_updated_at: when the nightly clustering run that every score is computed from last finished (ISO 8601, or null before the first run). Labels added after that moment are not in any cluster yet and cannot have changed a score until the next run.

The presets object holds named weight vectors (magnitudes; a type's sign is fixed by its base weight): default is the engine's own weights, barriers weighs problem types half again as much, infrastructure does the same for feature types, and missing_ramps doubles missing curb ramps. They are named by what they change, not by whom they are for — a weighting that claims to represent a disability community would need that community's involvement and the literature behind it — and every value is published, so a lens hides nothing.

Street grade

This API says grade for a street's steepness along its length, the running grade of its centerline, and never slope, which accessibility standards also use for a sidewalk's cross slope: that tilt across the walking surface cannot be measured from a centerline and is not reported.

Every street also carries its running grade, sampled along its centerline from a bare-earth elevation model. Grade needs no labeling, so it is there for unaudited streets too, and it is part of the score: a street steep enough to pass the walking-surface limit carries a negative grade_term, which is the one part of segment_score that sub_scores does not explain. A street with no sampled grade — including every street in a city whose grades have not been imported — carries a grade_term of 0 and is scored from its labels alone. Recomputing the score says how to weigh grade differently, or out. The street is the right thing to measure: PROWAG R302.4.1 caps a pedestrian route at 5% except where the adjacent street is steeper, in which case the sidewalk may match the street. Cross slope cannot be recovered from a centerline sample and is not reported.

A bare-earth model removes bridges and knows nothing of tunnels, so a street on a structure reports grade_quality: "structure" and no grade, not the grade of the ravine beneath it. The grade of a bridge deck is out of reach of any such model. One street's elevation profile, the one grade field too heavy for a city-wide file, is served by the Street Grade API.

Elevation model credits

Each street names the model it was sampled from in dem_source. If you publish the grade fields, credit the model as below, and cite it where you would cite data; /v3/api/accessScoreConfig lists the ones this city uses under grade.sources, with the same credit lines and citations. How the grades are sampled from the model, and how accurate they are, is on the Street Grade API page. A city sampled from rasters that are not in this table yet is credited by its dem_source alone.

dem_sourceElevation modelCreditLicenceCitation
usgs-3dep-10m USGS 3DEP 1/3 arc-second seamless DEM Elevation: U.S. Geological Survey, 3D Elevation Program Public domain U.S. Geological Survey, 2024, 1/3rd arc-second Digital Elevation Models (DEMs) - USGS National Map 3DEP Downloadable Data Collection: U.S. Geological Survey.

Quick Download

Download street AccessScore data directly in your preferred format:

Note: This downloads scores for all streets. For filtered data, use the API Query Parameters described below.

Query Parameters

All parameters are optional.

Note: When multiple location filters are provided (bbox, regionId, and regionName), bbox takes precedence over region filters, and regionId takes precedence over regionName. A region filter is resolved to the region's bounding box, and the streets are then trimmed back to that region.

ParameterTypeDescription
bbox string Filter by bounding box, as minLongitude,minLatitude,maxLongitude,maxLatitude (e.g., -74.04,40.88,-74.00,40.91), WGS84 (EPSG:4326). If omitted, the city's default bounding box is used.
regionId integer Score only streets within the region with this id. Takes precedence over regionName; bbox takes precedence over both.
regionName string Score only streets within the region with this name. Used only when bbox and regionId are absent.
filetype string Output format. Options: geojson (default), csv, shapefile, geopackage.
inline boolean Whether to display the file inline rather than as an attachment. Default: false.

Responses

Success Response (200 OK)

On success, the API returns 200 OK and the requested data in the specified filetype format.

GeoJSON Format (Default)

Returns a GeoJSON FeatureCollection where each feature is a street segment (LineString, WGS84 / EPSG:4326).

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [[-74.0243, 40.8839], [-74.0245, 40.8836]]
      },
      "properties": {
        "street_edge_id": 766,
        "osm_way_id": 11584845,
        "region_id": 8,
        "score": 0.6444,
        "segment_score": 0.263,
        "start_intersection_id": 412,
        "end_intersection_id": 415,
        "start_intersection_score": 0.8176,
        "end_intersection_score": 0.8525,
        "audit_count": 2,
        "length_meters": 142.7,
        "label_count": 4,
        "mean_grade": 0.0412,
        "max_grade": 0.0687,
        "net_grade": -0.0398,
        "total_climb_meters": 0.2,
        "total_descent_meters": 5.9,
        "meters_over_5pct": 48.0,
        "meters_over_8pct": 0.0,
        "grade_confidence": "high",
        "grade_quality": "measured",
        "dem_source": "usgs-3dep-10m",
        "grade_term": -0.561,
        "cluster_counts": {
          "CurbRamp": 0, "NoCurbRamp": 0, "Obstacle": 0, "SurfaceProblem": 1,
          "Crosswalk": 1, "Signal": 0, "NoSidewalk": 0
        },
        "sub_scores": {
          "CurbRamp": 0.0, "NoCurbRamp": 0.0, "Obstacle": 0.0, "SurfaceProblem": -0.4695,
          "Crosswalk": 0.0, "Signal": 0.0, "NoSidewalk": 0.0
        },
        "severity_counts": {
          "CurbRamp": {"1": 0, "2": 0, "3": 0, "null": 0},
          "NoCurbRamp": {"1": 0, "2": 0, "3": 0, "null": 0},
          "Obstacle": {"1": 0, "2": 0, "3": 0, "null": 0},
          "SurfaceProblem": {"1": 0, "2": 1, "3": 0, "null": 0},
          "Crosswalk": {"1": 0, "2": 0, "3": 1, "null": 0},
          "Signal": {"1": 0, "2": 0, "3": 0, "null": 0},
          "NoSidewalk": {"1": 0, "2": 0, "3": 0, "null": 0}
        },
        "tag_adjustments": {
          "CurbRamp": 0.0, "NoCurbRamp": 0.0, "Obstacle": 0.0, "SurfaceProblem": 0.0,
          "Crosswalk": 0.0, "Signal": 0.0, "NoSidewalk": 0.0
        }
      }
    },
    ...
  ]
}
GeoJSON Field Descriptions
Field PathTypeDescription
geometry.coordinatesarray[number]Coordinate pairs forming the street's path, in [longitude, latitude] (WGS84 / EPSG:4326).
properties.street_edge_idintegerProject Sidewalk's unique identifier for this street segment.
properties.osm_way_idintegerOpenStreetMap Way ID for the street, if available.
properties.street_namestringThe street's name, from its OpenStreetMap way's name tag; null for an unnamed way.
properties.region_idintegerIdentifier for the region the street belongs to.
properties.scorenumberHeadline AccessScore in (0, 1); higher is more accessible. The mean of segment_score, start_intersection_score, and end_intersection_score over those that are not null; null when all three are.
properties.segment_scorenumberThe street's own segment score in (0, 1), from the clusters in cluster_counts. null when the street has not been audited.
properties.start_intersection_idintegerThe intersection at the start of the street's geometry (see the Intersections API); null when that end is a dead end or a mere way split.
properties.end_intersection_idintegerThe intersection at the end of the street's geometry; null likewise.
properties.start_intersection_scorenumberThat intersection's score; null when there is none, it is unscored, or it is grade-separated.
properties.end_intersection_scorenumberThat intersection's score; null likewise.
properties.audit_countintegerNumber of completed (high-quality) audits of this street.
properties.length_metersnumberStreet length in meters (geodesic). Length-weights region scores and normalizes the along-length terms.
properties.label_countintegerNumber of labels contributing to this street's segment clusters.
properties.mean_gradenumberThe street's mean absolute running grade over every 10 m baseline, as a fraction (0.05 is a 5% grade). Like every grade field it comes from an elevation model, not from labels, so an unaudited street has it too; see Street grade. null where the street has not been sampled or has no usable profile (grade_quality says which).
properties.max_gradenumberThe steepest absolute grade over any 30 m baseline (any 10 m baseline on a street shorter than 30 m). Never below mean_grade.
properties.net_gradenumberEnd-to-end grade, signed in the direction of the street's geometry: negative where the street runs downhill from its first coordinate to its last. The one grade field a coarse (30 m) elevation model supports, so it can be set while the others are null.
properties.total_climb_metersnumberSummed rise along the street in the direction of its geometry, in meters.
properties.total_descent_metersnumberSummed fall along the street in the same direction, in meters.
properties.meters_over_5pctnumberMeters of the street steeper than 5% (1:20), the ADA / PROWAG running-slope limit for a walking surface.
properties.meters_over_8pctnumberMeters of the street steeper than 8.33% (1:12), the limit for a ramp; the field is named for the round figure. Never more than meters_over_5pct.
properties.grade_confidencestringhigh for an elevation model at 10 m or finer, medium to 20 m, low beyond. null where the street has not been sampled.
properties.grade_qualitystringmeasured; structure (a bridge, tunnel, or covered way, which a bare-earth model cannot see, so every grade is null); suspect (the sampled profile was implausible, so the grades come from a straight line between the street's ends, or are null); or no_data (the model has nothing under the street).
properties.dem_sourcestringThe elevation model the street was sampled from, which is what its credit is keyed on. null where the street has not been sampled.
properties.grade_termnumberWhat the street's grade adds to the segment's pre-sigmoid total under the engine's grade settings; never positive, and 0 on a street with no sampled grade or one gentler than the walking-surface limit. Grade is not a label type, so it has no sub_scores entry; it is published separately so that logit(segment_score) = Σ sub_scores + grade_term holds, and so that subtracting it recovers the label-only score.
properties.cluster_countsobjectNumber of clusters of each label type scoring the segment, keyed by label-type name: the along-length types, plus any corner-type cluster not attributed to an intersection.
properties.sub_scoresobjectContribution of each label type to the segment's pre-sigmoid total, keyed by label-type name; with grade_term the values sum to logit(segment_score), so they explain how it was composed. Per-cluster types report the sum over their clusters, length-normalized where the type is; NoSidewalk reports the street's single pooled term (see How the score is computed), which does not scale with cluster_counts.NoSidewalk.
properties.severity_countsobjectNumber of segment clusters of each label type in each rating bucket ("1", "2", "3", or "null" for unrated clusters), keyed by label-type name. The buckets of a type sum to its cluster_counts entry.
properties.tag_adjustmentsobjectThe summed adjustment of the active tags of each label type, keyed by label-type name: the part of sub_scores that no weight scales, before length normalization. With severity_counts, length_meters, and the scoring configuration, enough to recompute the segment score under your own weights.

CSV Format

If filetype=csv, the first row is the header. The per-type objects are flattened into one column per label type, each named for its path through the JSON: cluster_counts.<type>, sub_scores.<type>, severity_counts.<type>.1 through .3 plus .null, and tag_adjustments.<type>; the geometry is simplified to start/end points.

street_edge_id,osm_way_id,street_name,region_id,score,segment_score,start_intersection_id,end_intersection_id,start_intersection_score,end_intersection_score,audit_count,length_meters,label_count,mean_grade,max_grade,net_grade,total_climb_meters,total_descent_meters,meters_over_5pct,meters_over_8pct,grade_confidence,grade_quality,dem_source,grade_term,cluster_counts.CurbRamp,…,cluster_counts.NoSidewalk,sub_scores.CurbRamp,…,sub_scores.NoSidewalk,severity_counts.CurbRamp.1,severity_counts.CurbRamp.2,severity_counts.CurbRamp.3,severity_counts.CurbRamp.null,…,severity_counts.NoSidewalk.null,tag_adjustments.CurbRamp,…,tag_adjustments.NoSidewalk,start_point,end_point
766,11584845,Queen Anne Road,8,0.6444,0.263,412,415,0.8176,0.8525,2,142.7,4,0.0412,0.0687,-0.0398,0.2,5.9,48.0,0.0,high,measured,usgs-3dep-10m,-0.561,0,…,0,0.0,…,0.0,0,0,0,0,…,0,0.0,…,0.0,"-74.0243,40.8839","-74.0245,40.8836"
...

The full header, in order: the thirteen leading columns, the ten grade columns (mean_grade through dem_source) and grade_term, then cluster_counts.<type> for each of the 7 scored types, sub_scores.<type> for each, the four severity_counts.<type>.* buckets for each, tag_adjustments.<type> for each, then start_point and end_point. Types are always in the order CurbRamp, NoCurbRamp, Obstacle, SurfaceProblem, Crosswalk, Signal, NoSidewalk.

Shapefile Format

If filetype=shapefile, the response is a ZIP archive of Shapefile components (.shp, .shx, .dbf, .prj, .cpg). Text longer than 254 bytes is truncated. Because the DBF format truncates column names at 10 characters, the columns use short codes: segScore, sIntId / eIntId, and sIntScore / eIntScore for the headline's components, meanGrade, maxGrade, netGrade, climbM, descentM, mOver5pct, mOver8pct, gradeConf, gradeQual, demSource and gradeTerm for grade, and per type cluster count nCRamp, sub-score sCRamp, cluster count per rating bucket n1CRamp, n2CRamp, n3CRamp and n0CRamp (unrated), and tag adjustment tCRamp; the GeoJSON, CSV, and GeoPackage formats keep the full names.

GeoPackage Format

If filetype=geopackage, the response is a GeoPackage (.gpkg) file with full geometry and the same fields, in the same order, as the GeoJSON properties. The per-type columns are named as in the CSV but with each dot turned into an underscore, since ArcGIS doesn't allow dots in column names: cluster_counts_CurbRamp, sub_scores_CurbRamp, severity_counts_CurbRamp_1 through _3 plus _null, and tag_adjustments_CurbRamp.

Error Responses

  • 400 Bad Request: Invalid parameter values (e.g., malformed bounding box, non-positive or unknown region id).
  • 429 Too Many Requests: The same file is already being built for an earlier request; wait Retry-After seconds and try again. A HEAD request gets the same answer without building anything.
  • 500 Internal Server Error: An unexpected error occurred on the server.
  • 503 Service Unavailable: A whole-city request (no bbox or region filter) found the city's scores not yet cached — after a deploy, or in a long-idle city — and they are still being computed. Wait Retry-After seconds (30) and repeat the request; the body's code is STILL_COMPUTING.

Response Headers

  • X-File-Size: On a Shapefile, GeoPackage or zipped-CSV download, the file's size in bytes. Sent alongside Content-Length, and still present when the response is gzipped, which drops it — use it to show download progress.

Error Response Body

All errors are returned as RFC 7807 “problem details” with the application/problem+json content type and the following structure:

{
  "type": "about:blank",          // RFC 7807 problem-type URI ("about:blank" means no type beyond the status)
  "title": "Invalid Parameter",   // Short, human-readable summary of the problem type (stable for a given code)
  "status": 400,                  // HTTP status code (also repeated in the body)
  "detail": "Invalid value for the bbox parameter. Expected format: minLng,minLat,maxLng,maxLat.", // This occurrence
  "code": "INVALID_PARAMETER",    // Stable, machine-readable error code you can branch on
  "parameter": "bbox"             // Extension member: the specific parameter at fault (omitted when not applicable)
}

Best Practices

  • Treat the score as relative, not absolute: the weights are experimental. Use scores to compare streets, not as a calibrated index.
  • Read the breakdown: segment_score and the two intersection scores show which part of a trip along the street is the problem, and cluster_counts and sub_scores explain the segment.
  • Mind audit coverage: a null segment_score means the street has not been audited — absence of data, not poor accessibility. Its headline may still carry its crossings' scores.
  • Roll up to neighborhoods: use the AccessScore: Regions API for length-weighted, region-level scores.

Contribute

Project Sidewalk is an open-source project created by the Makeability Lab and hosted on GitHub. We welcome your contributions! If you found a bug or have a feature request, please open an issue on GitHub.

You can also email us at sidewalk@cs.uw.edu

Project Sidewalk in Your City!

If you are interested in bringing Project Sidewalk to your city, please read our Wiki page.

On This Page