# libraryapi.dev — LLM Reference libraryapi.dev is a REST API for US public library facility, hours, services, and statistics data. Built on the federal IMLS Public Libraries Survey (PLS) — an annual census of every public library system and outlet in the United States. Public domain data, commercially usable. Base URL: https://api.libraryapi.dev Current version: v1 Data vintage: IMLS PLS FY 2023 (released August 2025) Coverage: 9,252 library systems + 17,586 outlets across the 50 states, DC, and outlying territories (PR, GU, MP, AS, VI). Response rate: 96-97%. --- ## Authentication Pass an API key on every request using one of: Header: X-API-Key: sk_live_... Header: Authorization: Bearer sk_live_... API keys are obtained free at https://libraryapi.dev/pricing (500 requests/month, no credit card). GET /v1/health does NOT require an API key. --- ## Rate Limits | Plan | Per minute | Per month | |------------|------------|-----------| | Free | 10 | 500 | | Starter | 60 | 10,000 | | Pro | 120 | 50,000 | | Growth | 300 | 200,000 | Exceeding per-minute limit → 429 RATE_LIMITED Exceeding monthly limit → 402 QUOTA_EXCEEDED Monthly quotas reset on the 1st of each calendar month. --- ## Response Envelope Every successful response uses this envelope: { "data": , "meta": { "requestId": "req_d00aa00a7fee", "creditsUsed": 1, "creditsRemaining": 499 }, "source": { "imlsYear": "FY 2023", "updatedAt": "2025-08-15", "freshnessDays": 273 } } All field names in responses are camelCase. Each API call costs 1 credit regardless of results returned. --- ## Key Concepts **Library system** (also "administrative entity" or "AE" in IMLS docs): The administrative unit — typically a county, city, or multi-jurisdictional library system that operates one or more outlets. Identified by FSCSKEY (a 6-character ID like "CA0109"). ~9,252 systems nationwide. **Outlet**: The physical service point — a main library, a branch, a bookmobile, or a books-by-mail unit. Each outlet has a compound ID combining its parent FSCSKEY and a sequence number (e.g. "CA0109-004"). ~17,586 outlets nationwide. **Outlet types** (outletType field): central Main library of a system branch Satellite branch bookmobile Mobile library vehicle books-by-mail Mail-based service (no fixed location) Bookmobile and books-by-mail outlets sometimes lack coordinates — handle null geo fields gracefully. --- ## Endpoints ### GET /v1/outlets Find the nearest public library outlets to an address or coordinate. Returns outlets sorted by distance ascending. Query parameters: address string Street address (geocoded with US Census, fallback Nominatim) lat number Latitude (use with lng) lng number Longitude (use with lat) radius_miles number Search radius. Min 0.1, max 50, default 10 limit integer Max results. Min 1, max 100, default 10 Provide either address OR lat+lng. Example request: GET /v1/outlets?address=14901+Dale+Evans+Pkwy,+Apple+Valley,+CA&radius_miles=10&limit=3 Example response: { "data": [ { "outletId": "CA0109-004", "fscsId": "CA0109", "name": "Newton T. Bass Apple Valley Branch Library", "outletType": "branch", "parentSystem": { "fscsId": "CA0109", "name": "San Bernardino County Library" }, "address": { "street": "14901 Dale Evans Parkway", "city": "Apple Valley", "state": "CA", "zip": "92307", "zip4": "3061" }, "phone": "(760) 247-2022", "geo": { "lat": 34.524928, "lng": -117.21587, "geocodeQuality": "high" }, "service": { "annualHours": 1520, "weeksOpen": 52, "squareFootage": 19412 }, "status": "no change", "dataYear": "FY 2023", "distanceMiles": 0.14 } ], "meta": { "requestId": "req_d00aa00a7fee", "creditsUsed": 1, "creditsRemaining": 499 }, "source": { "imlsYear": "FY 2023", "updatedAt": "2025-08-15", "freshnessDays": 273 } } --- ### GET /v1/outlets/{outlet_id} Get a single outlet by its compound ID (format: FSCSKEY-seq). Path parameter: outlet_id string e.g. "CA0109-004" Response: same Outlet schema as above, wrapped in "data": { ... } (not an array). --- ### GET /v1/libraries/{fscs_id} Get the full profile for a library system — including collections, usage, programs, technology, finance, and staffing. Path parameter: fscs_id string 6-character FSCS library system ID (e.g. "CA0109") Example request: GET /v1/libraries/CA0109 Example response: { "data": { "fscsId": "CA0109", "name": "San Bernardino County Library", "state": "CA", "county": "San Bernardino", "address": { "street": "777 East Rialto Ave", "city": "San Bernardino", "state": "CA", "zip": "92415" }, "phone": "(909) 387-2220", "legalBasis": "County/Parish", "serviceArea": { "population": 1263869, "centralLibraries": 0, "branches": 32, "bookmobiles": 0 }, "collections": { "printVolumes": 1104531, "ebooks": 414337, "audioPhysical": 24111, "audioDownloadable": 33015, "videoPhysical": 74792, "videoDownloadable": 0 }, "usage": { "annualVisits": 1476017, "registeredBorrowers": 223845, "totalCirculation": 4512254, "kidsCirculation": 2672666, "physicalCirculation": 3611957, "electronicCirculation": 900297, "programs": { "total": 5273, "kids": 4380, "youngAdult": 234, "attendanceTotal": 166411, "attendanceKids": 107000, "attendanceYa": 3902 }, "technology": { "publicComputers": 793, "computerSessions": 318909, "wifiSessions": null, "websiteVisits": null } }, "finance": { "totalRevenue": 28327522, "localRevenue": 26882284, "stateRevenue": 223113, "federalRevenue": 277543, "otherRevenue": 944582, "totalExpenditures": 29130766, "perCapitaExpenditure": 23.05, "staffFte": { "mlsLibrarians": 5.0, "librarians": 39.0, "other": 82.0, "total": 121.0 } }, "outletsCount": 32, "dataYear": "FY 2023" }, "meta": { ... }, "source": { ... } } --- ### GET /v1/libraries/search Search library systems by name, state, and/or city. Provide at least one parameter. Query parameters: name string System name (full-text search, e.g. "brooklyn") state string Two-letter state abbreviation (e.g. "NY") city string City name (substring, case-insensitive) limit integer Results per page. Min 1, max 100, default 20 offset integer Pagination offset, default 0 Example request: GET /v1/libraries/search?name=brooklyn&state=NY Returns a paginated array of library system summary records (same shape as the full system response, without the joined collections/usage/finance sub-objects). --- ### GET /v1/states/{code}/summary State-level rollup statistics for all FSCS-compliant library systems in a state. Path parameter: code string Two-letter state abbreviation (e.g. "CA") Example request: GET /v1/states/CA/summary Example response: { "data": { "state": "CA", "dataYear": "FY 2023", "totals": { "librarySystems": 186, "outlets": 1192, "serviceAreaPopulation": 1109153789, "annualVisits": 1822657666, "totalCirculation": 5733910183, "totalExpenditures": 57571616061 }, "averages": { "perCapitaExpenditure": 57.66, "outletsPerSystem": 6.41 } }, "meta": { ... }, "source": { "imlsYear": "FY 2023", "updatedAt": "2025-08-15" } } --- ### GET /v1/health Service health check. Returns DB connectivity and data freshness. Does NOT consume a credit. Does NOT require an API key. Example response: { "status": "ok", "db": true, "source": { "imls_year": "FY 2023", "updated_at": "2025-08-15", "freshness_days": 273 } } --- ## Outlet Object Schema outletId string Compound ID — format: "{FSCSKEY}-{seq}" fscsId string Parent system's 6-char FSCSKEY name string Outlet name (already title-cased) outletType enum "central" | "branch" | "bookmobile" | "books-by-mail" parentSystem.fscsId string Same as fscsId — convenience copy parentSystem.name string Parent system's name address.street string address.city string address.state string Two-letter abbreviation address.zip string 5-digit ZIP address.zip4 string ZIP+4 extension (often null) phone string Formatted "(XXX) XXX-XXXX" geo.lat number Latitude (WGS84) geo.lng number Longitude (WGS84) geo.geocodeQuality enum "high" | "medium" | "low" — from IMLS geocoding confidence service.annualHours integer Total hours open per year service.weeksOpen integer Weeks of operation per year (max 52) service.squareFootage integer Building square footage status string Outlet status from IMLS STATSTRU field dataYear string Fiscal year of the data (e.g. "FY 2023") distanceMiles number Only present in /v1/outlets list responses --- ## Library System Object Schema (full profile) fscsId string 6-char FSCS library system ID name string Official system name state string Two-letter abbreviation county string County name address object System HQ address (street/city/state/zip/zip4) phone string Formatted legalBasis string e.g. "County/Parish", "Municipal", "Non-profit Association" serviceArea.population integer Legal service area population (POPU_LSA) serviceArea.centralLibraries integer Number of central libraries serviceArea.branches integer Number of branch outlets serviceArea.bookmobiles integer Number of bookmobile units collections.printVolumes integer Physical books held collections.ebooks integer E-book titles collections.audioPhysical integer Physical audio materials collections.audioDownloadable integer Downloadable audio collections.videoPhysical integer Physical video collections.videoDownloadable integer Downloadable video usage.annualVisits integer In-person visits per year usage.registeredBorrowers integer Active library card holders usage.totalCirculation integer Total checkouts (physical + electronic) usage.kidsCirculation integer Children's material checkouts usage.physicalCirculation integer Physical-only checkouts usage.electronicCirculation integer E-book / audio downloads usage.programs.total integer Programs offered (year) usage.programs.kids integer Children's programs (ages 0-11) usage.programs.youngAdult integer Teen / YA programs usage.programs.attendanceTotal integer Total attendance, all programs usage.programs.attendanceKids integer Children's program attendance usage.programs.attendanceYa integer YA program attendance usage.technology.publicComputers integer Public-access computer terminals usage.technology.computerSessions integer Computer-use sessions per year usage.technology.wifiSessions integer Wifi sessions per year (often null) usage.technology.websiteVisits integer Website visits per year (often null) finance.totalRevenue integer Total operating revenue (USD) finance.localRevenue integer Local government revenue finance.stateRevenue integer State revenue finance.federalRevenue integer Federal revenue finance.otherRevenue integer All other revenue finance.totalExpenditures integer Total operating expenditures finance.perCapitaExpenditure number Expenditures / service-area population finance.staffFte.mlsLibrarians number Librarians with MLS degree (FTE) finance.staffFte.librarians number All librarians (FTE) finance.staffFte.other number Other paid staff (FTE) finance.staffFte.total number Total paid staff (FTE) outletsCount integer Number of outlets in this system dataYear string "FY 2023" Any field may be null when not reported by the library. IMLS imputes some values; transparency-preserving imputation flags are tracked in our DB but not yet exposed on responses. --- ## Error Response Schema All errors return: { "detail": { "code": "ERROR_CODE", "message": "Human-readable description" } } Error codes: 400 INVALID_PARAMS Required parameters missing or conflicting 400 INVALID_ADDRESS Address could not be geocoded 401 INVALID_API_KEY Key missing, invalid, or revoked 402 QUOTA_EXCEEDED Monthly request quota reached 404 LIBRARY_NOT_FOUND No library system or outlet found for ID 404 NO_LIBRARIES_NEARBY No outlets within the requested radius 429 RATE_LIMITED Too many requests per minute 500 INTERNAL_ERROR Server error --- ## Common LLM Use Cases Finding the nearest library to an address: GET /v1/outlets?address=
&radius_miles=10&limit=5 → Returns outlets sorted by distance. Use data[0] for nearest. Getting hours and services for a specific library: GET /v1/outlets/ → Returns outlet with service.annualHours, service.weeksOpen, service.squareFootage. Estimating weekly hours from annual hours: weeklyHours = round(annualHours / weeksOpen) e.g. 1520 / 52 = 29 hours/week Looking up a library system's full profile (financials, collections, etc.): GET /v1/libraries/ → Returns the parent system with all sub-objects populated. Comparing libraries within a state: GET /v1/states//summary → Aggregate rollup (totals + averages). Finding all libraries in a city: GET /v1/libraries/search?city=brooklyn&state=NY --- ## Data Source All records trace back to the IMLS Public Libraries Survey (PLS): - Agency: Institute of Museum and Library Services - Collection agent: American Institutes for Research (AIR) - Authority: Museum and Library Services Act of 2018 (PL 115-410), Section 210 - License: Federal public-use, commercial use explicitly permitted - Frequency: Annual; data collected Jan-Aug each year - Coverage: 50 states + DC + Puerto Rico + Guam + Northern Mariana Islands + American Samoa + US Virgin Islands - Source URL: https://www.imls.gov/research-evaluation/surveys/public-libraries-survey-pls We add geocoding (US Census + Mapbox), PostGIS spatial indexing for sub-100ms nearest-outlet queries, and a clean REST envelope. The federal CSV is reloaded once per year — annual updates are stable and timely (within ~1 week of IMLS release). --- ## SDK and MCP Server Python SDK: pip install libraryapi-sdk (github.com/library-api/libraryapi-python · Python module name: libraryapi) Node.js SDK: npm install libraryapi-sdk (github.com/library-api/libraryapi-js) MCP Server: uvx libraryapi-mcp (github.com/library-api/libraryapi-mcp) [planned] --- ## Related products libraryapi.dev is the sister product to: - districtapi.dev — US public school district + school data (same architecture, same audience) Bundle Starter tiers from both for $39/mo combined — useful for civic tech, proptech, K-12 SaaS, and AI agents that need both school and library coverage for a given address. Contact hello@libraryapi.dev for the bundle. --- ## Links Homepage: https://libraryapi.dev Demo: https://libraryapi.dev/demo Docs: https://libraryapi.dev/docs Pricing: https://libraryapi.dev/pricing Status: https://libraryapi.dev/status GitHub: https://github.com/library-api Support: hello@libraryapi.dev