Discover/DigitalSF API
live

DigitalSF APIdigitalsf.org

Search and retrieve catalogue metadata from the San Francisco Public Library's DigitalSF digital collections, including titles, dates, creators, and image URLs.

Endpoint health
verified 2h ago
search_photos
get_photo
2/2 passing latest checkself-healing
Endpoints
2
Updated
2h ago

What is the DigitalSF API?

The DigitalSF API provides 2 endpoints for searching and retrieving public catalogue records from the San Francisco Public Library's DigitalSF digital collections. Use search_photos to query by street address, street name, or any keyword and receive paginated results with stable item IDs, titles, photographer attributions, and image URLs. Use get_photo to fetch the full record for any individual item, including verbatim notes, genre terms, series data, and preferred citation text.

This call costs3 credits / call— charged only on success
Try it
1-based result page over the site's result stream.
Records per page; values above 100 are clamped to 100.
Free-text search string, e.g. a street address or street name. Double-quote it for an exact phrase match.
When true, applies the site's own 'Type: Still image' facet so text records (newspapers, documents) are excluded. The facet is the site's; its counts can differ from the content_type field on individual records.
api.parse.bot/scraper/5ac4f6ed-b7af-43b3-80a2-9ae093bd877c/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/5ac4f6ed-b7af-43b3-80a2-9ae093bd877c/search_photos?page=2&limit=3&query=Cortland+Avenue&still_images_only=true' \
  -H 'X-API-Key: $PARSE_API_KEY'
All endpoints · 2 totalmissing one? ·

Searches the DigitalSF catalogue with a free-text query (a street address such as '439 Cortland Avenue', a street name such as 'Goettingen Street', or any keyword; wrap the query in double quotes for an exact phrase) and returns one page of catalogue records in the site's default relevance/date order. Each item is one catalogue record with its stable item_id, item_url (pass unchanged to get_photo), title, verbatim notes and address/parcel note when catalogued, catalogued creation and capture date text with a stated meaning and a format-derived precision (null when not catalogued), creators/photographers, dimensions (null when not given), rights statement/label/URL, a public thumbnail URL and the public image file URLs listed by the site. heading and location are always null: the catalogue does not publish camera heading or coordinates. A search hit only means the record text matched the query; it is not a claim that the photograph depicts the requested building. Rights URL: the catalogue's metadata export carries the rights label but not the link; the site's public item page renders that label as a rightsstatements.org link. search_photos reads that link from one item page per distinct rights label on the returned page (at most 4 extra round trips) and applies it to every item on the page carrying the identical label; rights_url_source is then 'site_item_page_same_label'. If the item page gives no link, or more than 4 distinct labels occur on one page, rights_url stays null with rights_url_source null — a null never implies permission; call get_photo for the item's own page link. Pagination: page (1-based) and limit (1-100, clamped) drive a true offset over the site's result stream; total_count is the site's own reported record count (null only if the site omits it); has_more/next_page say whether a further page exists. An empty items array with total_count 0 means the site found no records for the query (a valid empty result); site outages or challenges surface as non-success envelopes instead. Two site round trips per call plus one per distinct rights label.

Input
ParamTypeDescription
pageinteger1-based result page over the site's result stream.
limitintegerRecords per page; values above 100 are clamped to 100.
queryrequiredstringFree-text search string, e.g. a street address or street name. Double-quote it for an exact phrase match.
still_images_onlybooleanWhen true, applies the site's own 'Type: Still image' facet so text records (newspapers, documents) are excluded. The facet is the site's; its counts can differ from the content_type field on individual records.
Response
{
  "type": "object",
  "fields": {
    "page": "integer page requested",
    "items": "array of catalogue records; each has item_id (stable string record id), local_identifier (library accession number or null), item_url (public item page URL, input to get_photo), title, alternative_titles (array), description (string or null), notes (array of verbatim catalogue notes), address_or_parcel_verbatim (verbatim address/parcel note or null), date_created_text/date_created_meaning/date_created_precision (verbatim catalogued creation date, its meaning, and precision one of day|month|year|range|approximate_or_text; all null when unknown), date_captured_text/date_captured_meaning/date_captured_precision (same for a catalogued capture date; null when not catalogued), date_sort_year (string or null), creators (array of {name, role, dates}), photographers (array of creator names whose role is photographer), physical_description, dimensions (string or null), content_type, subjects/place_subjects/genres (arrays), collection, series, call_number, citation, rights_statement, rights_label, rights_url (rightsstatements.org link as rendered on the site's item page for this label, or null when the site shows none), rights_url_source ('catalogue_record' when the metadata export itself carried the link, 'site_item_page_same_label' when read from a DigitalSF item page bearing the identical rights label, null when rights_url is null), heading (always null), location (always null), thumbnail_url, image_urls (array of {url, size_bytes}), external_links (array of {url, label})",
    "limit": "integer page size applied after clamping",
    "query": "the search string as sent",
    "has_more": "boolean, whether another page exists",
    "next_page": "integer next page number, or null when has_more is false",
    "total_count": "integer total records the site reports for the query, or null if the site did not report one",
    "still_images_only": "boolean, whether the still-image facet was applied"
  },
  "sample": {
    "data": {
      "page": 1,
      "items": [
        {
          "notes": [
            "Address. Box 1, Cortland Avenue, 439."
          ],
          "title": "439 Cortland Avenue, Arrow Pharmacy",
          "genres": [
            "Photographs"
          ],
          "series": "San Francisco Historical Photograph Collection",
          "heading": null,
          "item_id": "54740",
          "citation": "[Identification of item], San Francisco Office of Assessor-Recorder Photographs (SFP 23), San Francisco History Center, San Francisco Public Library.",
          "creators": [],
          "item_url": "https://digitalsf.org/record/54740",
          "location": null,
          "subjects": [
            "Streets--Cortland Avenue."
          ],
          "collection": "San Francisco Office of Assessor-Recorder Photographs",
          "dimensions": "4 x 5 in.",
          "image_urls": [
            {
              "url": "https://digitalsf.org/record/54740/files/AAM-1192.tiff",
              "size_bytes": 18093224
            }
          ],
          "rights_url": "https://rightsstatements.org/page/NoC-US/1.0/",
          "call_number": "SFP 23",
          "description": null,
          "content_type": "Still image",
          "rights_label": "No Copyright – United States",
          "photographers": [],
          "thumbnail_url": "https://digitalsf.org/nanna/thumbnail/v2/54740?redirect=1",
          "date_sort_year": "1951",
          "external_links": [],
          "place_subjects": [
            "San Francisco (Calif.)"
          ],
          "local_identifier": "AAM-1192",
          "rights_statement": "No copyright restrictions under U.S. law.",
          "date_created_text": "1951-05-08",
          "rights_url_source": "site_item_page_same_label",
          "alternative_titles": [
            "Cortland Avenue"
          ],
          "date_captured_text": null,
          "date_created_meaning": "date of creation/publication as catalogued (MARC 260/264 $c), verbatim",
          "physical_description": "1 negative : b&w",
          "date_captured_meaning": null,
          "date_created_precision": "day",
          "date_captured_precision": null,
          "address_or_parcel_verbatim": "Address. Box 1, Cortland Avenue, 439."
        },
        {
          "notes": [
            "Folder: S.F. Streets-Cortland.",
            "Negative #4187"
          ],
          "title": "Cortland between Anderson and Ellsworth street",
          "genres": [
            "Photographs"
          ],
          "series": "San Francisco Historical Photograph Collection",
          "heading": null,
          "item_id": "52268",
          "citation": "[Identification of item], San Francisco Subjects Photograph Collection (SFP 162), San Francisco History Center, San Francisco Public Library.",
          "creators": [],
          "item_url": "https://digitalsf.org/record/52268",
          "location": null,
          "subjects": [
            "Streets--Cortland Avenue."
          ],
          "collection": "San Francisco Subjects Photograph Collection",
          "dimensions": null,
          "image_urls": [
            {
              "url": "https://digitalsf.org/record/52268/files/AAB-3366.tiff",
              "size_bytes": 19686112
            }
          ],
          "rights_url": "https://rightsstatements.org/page/NoC-US/1.0/",
          "call_number": "SFP 162",
          "description": null,
          "content_type": "Still image",
          "rights_label": "No Copyright – United States",
          "photographers": [],
          "thumbnail_url": "https://digitalsf.org/nanna/thumbnail/v2/52268?redirect=1",
          "date_sort_year": "1926",
          "external_links": [
            {
              "url": "https://oac.cdlib.org/findaid/ark:/13030/c8xg9zwc",
              "label": "Link to finding aid"
            }
          ],
          "place_subjects": [
            "San Francisco (Calif.)"
          ],
          "local_identifier": "AAB-3366",
          "rights_statement": "No copyright restrictions under U.S. law.",
          "date_created_text": "1926",
          "rights_url_source": "site_item_page_same_label",
          "alternative_titles": [],
          "date_captured_text": null,
          "date_created_meaning": "date of creation/publication as catalogued (MARC 260/264 $c), verbatim",
          "physical_description": "1 photographic print : b&w",
          "date_captured_meaning": null,
          "date_created_precision": "year",
          "date_captured_precision": null,
          "address_or_parcel_verbatim": null
        }
      ],
      "limit": 2,
      "query": "439 Cortland Avenue",
      "has_more": true,
      "next_page": 2,
      "total_count": 38,
      "still_images_only": false
    },
    "status": "success"
  }
}

About the DigitalSF API

Endpoints and What They Return

The search_photos endpoint accepts a required query string — a street address like 439 Cortland Avenue, a street name, or any keyword — and returns a page of catalogue records. Each record includes a stable item_id, a local_identifier (library accession number when available), verbatim title, and public item_url and image/thumbnail URLs. A total_count field indicates how many records the catalogue reports for the query, and has_more plus next_page support pagination through result sets. The optional still_images_only boolean applies the catalogue's own 'Type: Still image' facet to exclude documents and newspapers from results.

Filtering and Pagination

Pagination is controlled by page (1-based) and limit (capped at 100 records per request). Wrapping the query value in double quotes requests an exact phrase match from the catalogue's own search index. This is useful when a street name appears as a substring of many unrelated records. The still_images_only filter is particularly useful for photography research workflows where document-type records would add noise.

Full Record Lookup

get_photo accepts the item_url from any search_photos result — a URL of the form https://digitalsf.org/record/<id> — and returns the complete catalogue record. Beyond the search-result fields, this payload includes an array of verbatim notes, genres, series title, citation text, and a creators array with name, role, and dates for each attributed photographer or creator. The location and heading fields are present in the schema but not published by the source; both return null.

Reliability & maintenanceVerified

The DigitalSF API is a managed, monitored endpoint for digitalsf.org — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when digitalsf.org changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official digitalsf.org API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Last verified
2h ago
Latest check
2/2 endpoints passing
Maintenance
Monitored & self-healing
Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Map historical San Francisco street addresses to archival photographs using the query parameter of search_photos.
  • Build a photographer attribution index by aggregating the creators array (name, role, dates) across multiple get_photo results.
  • Enumerate all digitised items in a named series by searching for the series title and checking the series field in each full record.
  • Compile preferred citation strings for academic use via the citation field returned by get_photo.
  • Filter catalogue results to still images only (setting still_images_only to true) before embedding public thumbnail URLs in a web application.
  • Track accession numbers across a digitisation project by collecting local_identifier values from search_photos results.
  • Generate a rights-reviewed image list by coupling the item_url with verbatim notes that contain rights statements.
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo2005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min
Team$300/mo20,000300 req/min
Company$1,000/mo100,000500 req/min

Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does DigitalSF have an official developer API?+
No. The San Francisco Public Library's DigitalSF site at digitalsf.org does not publish a documented public developer API or data feed. This Parse API provides structured programmatic access to the public catalogue metadata.
What does get_photo return beyond what search_photos already includes?+
get_photo returns the full catalogue record: a notes array of verbatim catalogue notes (which often contain address or rights information), a genres array, a series title, a citation string, and a creators array with name, role, and dates for each attributed creator. The search result includes the item's title, item_id, and URLs but does not include these deeper fields.
Are there fields that are always null in responses?+
Yes. The location field (structured geographic coordinates or place name) and heading field (subject heading) are present in the response schema for both endpoints but consistently return null because the source catalogue does not publish that data in a retrievable form. Rights and address information, when available, appears inside the notes array as verbatim text rather than in a dedicated structured field.
Does the API support browsing by collection, subject heading, or date range?+
Not currently. The API covers free-text keyword search (with optional still-image filtering) and individual item lookup by URL or ID. Faceted browsing by collection, structured subject heading, or date range is not exposed as a parameter. You can fork this API on Parse and revise it to add collection-browse or date-range endpoints.
How large can a single page of search results be, and is there a total result count?+
The limit parameter controls page size and is clamped to a maximum of 100 records per request. The total_count field in the response reports the total number of matching records the catalogue returns for the query, though it may be null if the catalogue does not report one. Use has_more and next_page to walk through all pages.
Page content last updated . Spec covers 2 endpoints from digitalsf.org.
Related APIs in Government PublicSee all →