SchoolDigger Python SDK
Official Python client for the SchoolDigger API — K-12 school data for 120,000+ U.S. schools.
Installation
pip install schooldigger
Quick Start
import schooldigger
config = schooldigger.Configuration()
config.api_key["appID"] = "YOUR_APP_ID"
config.api_key["appKey"] = "YOUR_APP_KEY"
client = schooldigger.ApiClient(config)
# Search schools
api = schooldigger.SchoolsApi(client)
result = api.search_schools(st="WA", q="Lincoln")
for school in result.school_list:
print(f"{school.school_name} — {school.address.city}, {school.address.state}")
# Get a specific school by SchoolDigger ID
school = api.get_school("530966001632")
print(f"Enrollment: {school.school_yearly_details[0].number_of_students}")
API Classes
| Class | Methods |
|---|---|
SchoolsApi |
search_schools(), get_school() |
DistrictsApi |
search_districts(), get_district() |
RankingsApi |
get_school_rankings(), get_district_rankings() |
AutocompleteApi |
autocomplete_schools(), autocomplete_districts() |
Test scores in API 3.0
Pass include_ranges=True to get_school / get_district (without it, test scores are
as in API 2.4). Each test-score percent
(percent_met_standard, percent_tier1 ... percent_tier5) is either a number or an
APIReportedPercent object (status of range, suppressed, legacyImputed or derived,
with optional value, low, high), and is None when the state reported nothing. The SDK
exposes the union through .actual_instance:
school = api.get_school("330004800609", include_ranges=True)
for ts in school.test_scores or []:
v = ts.school_test_score.percent_met_standard if ts.school_test_score else None
v = v.actual_instance if v is not None else None
if v is None:
text = "not reported"
elif isinstance(v, (int, float)):
text = f"{v}%"
elif v.status == "suppressed":
text = "suppressed by the state"
elif v.low is not None and v.low <= 0:
text = f"< {v.high}%"
elif v.high is not None and v.high >= 100:
text = f">= {v.low}%"
elif v.low is not None:
text = f"{v.low}-{v.high}%"
else:
text = f"{v.value}%"
print(ts.year, ts.grade, ts.subject, text)
See Data Quality and Suppression for the full vocabulary and rendering rule. API 2.4 and below (SDK 1.x) return only exact values.
Low-income measure in API 3.1
SDK 3.0 targets API 3.1. School records from get_school, search_schools and
get_school_rankings carry low_income: the school's one low-income measure, type "FRL"
(free/reduced-price lunch eligible), "DC" (directly certified for free meals; used where the
school reports no usable free/reduced count) or "CEP" (likely serves free meals to all
students under the Community Eligibility Provision; no percent), with year, percent,
count, enrollment, community_eligibility_likely and statewide_free_meals. It is None
when the school has no usable value. FRL and DC are not comparable: don't sort one against the
other.
school = api.get_school("250309000385")
li = school.low_income
if li is None:
print("no low-income figure")
elif li.type == "CEP":
print(f"All students receive free meals (Community Eligibility, {li.year - 1}-{li.year % 100:02d})")
else:
label = "Free/reduced lunch eligible" if li.type == "FRL" else "Directly certified for free meals"
print(f"{label}: {li.percent}% ({li.year - 1}-{li.year % 100:02d})")
for y in school.school_yearly_details or []:
print(y.year, y.free_reduced_lunch, y.direct_certification)
Each yearly detail has free_reduced_lunch (count and percent, or a status of
communityEligibility, repeated or aboveEnrollment) and direct_certification. SDK 3.0
renames the school models for API 3.1, a breaking change for code that imports them by name (APISchoolFull31Ranges, APISchoolList31,
APISchoolSummary31, APISchoolListRank31, APISchoolSummaryRank31). See
Low-income measures.
Vaccination rates in API 3.1
SDK 3.1 adds vaccination to get_school: the state's published vaccination rates for the
school, with source (agency, url, headline_label, suppression_note, district_scope),
headline (the state's lead figure, e.g. kindergartners with all required vaccines: year,
grade_name, antigen, status, label, value, students, students_total,
exemption_rate), district_name / county_name / state_name, years_available,
grades_available and figures (each year, grade, vaccine and status, with the school's value
and the state's own district, county and state values). By default figures holds the headline
grade for its most recent year; pass include_vaccination_detail=True for every grade and year.
search_schools carries the headline alone on each school as vaccination. Both are None
when the state publishes no vaccination data for the school, so check before use.
Each value has a status: "exact" (pct), "range" (range_low / range_high),
"suppressed", "redactedCount", "countOnly" (see students) or "invalid".
school = api.get_school("530111000200", include_vaccination_detail=True)
v = school.vaccination
if v is None or v.headline is None or v.headline.value is None:
print("no vaccination headline")
else:
h, val = v.headline, v.headline.value
if val.status == "exact":
text = f"{val.pct}%"
elif val.status == "range":
text = f"{val.range_low}-{val.range_high}%"
else:
text = val.status
print(f"{h.label} ({h.year - 1}-{h.year % 100:02d}): {text} [{v.source.agency}]")
print(f"{len(v.figures)} figures for years {v.years_available}")
District endpoints are unchanged. See Vaccination rates.
Authentication
All API calls require an appID and appKey. Get your free API key at developer.schooldigger.com.
Documentation
Plans
| Plan | Price | Highlights |
|---|---|---|
| DEV/TEST | Free | Enterprise-level access, 20 calls/day |
| Basic | $19.90/mo | 1 year of data |
| Pro | $89/mo | Boundaries, geo search, finance |
| Enterprise | $189/mo | Full depth, boundary containment |
License
MIT
Metadata
Release files for schooldigger 3.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| schooldigger-3.1.0.tar.gz | 79.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| schooldigger-3.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 218.2 kB
Release files / schooldigger-3.1.0.tar.gz
| Download URL | schooldigger-3.1.0.tar.gz |
|---|---|
| Size | 79.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a2809ab504b7f5383fd00c436bb8d9fdea436b3eaf0a8902ec58ea1f37c840de
|
|
BLAKE2b-256 checksum How to use checksums |
83e1109b63fb8cffde34c8a33d272ade80a5a62b789ed9013fc2949d2ee3096a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / schooldigger-3.1.0-py3-none-any.whl
| Download URL | schooldigger-3.1.0-py3-none-any.whl |
|---|---|
| Size | 138.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ce7cdf24ff6ab0d202a4f405433c51903c57dfb87824ade9b714cdc260184ecc
|
|
BLAKE2b-256 checksum How to use checksums |
baec5ef9f28699400624800697e26f856a68b43d59859594588339f893507928
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for schooldigger 3.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for schooldigger-3.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.