How to Scrape K-12 School District Data and Test Scores (2026)

it looks like file write permission is being blocked. the article is ready — here is the full markdown body:

K-12 school district data is some of the most fragmented public data in existence — dozens of state education portals, inconsistent schemas, and test score exports locked behind clunky JavaScript dashboards that were last redesigned in 2014. if you need district-level enrollment figures, per-pupil spending, or NAEP and state assessment scores at scale, you will need a scraping strategy that handles both static state department sites and the dynamic report builders that most of the newer portals use.

Where the data actually lives

the U.S. has no single K-12 data repository. the main sources are:

  • National Center for Education Statistics (NCES) — Common Core of Data (CCD), NAEP Data Explorer, School Digest. bulk CSV downloads available, rate limits are lenient.
  • State Department of Education portals — 50 different sites. California uses DataQuest, Texas uses TEAL/TAPR, New York uses Report Cards. each has its own export format.
  • NWEA MAP / Renaissance STAR — vendor-level growth data. only accessible if your institution has a contract.
  • USASpending.gov and FOIA requests — federal grant data per district, useful for EdTech lead generation.

NCES is the easiest starting point. the CCD has district-level enrollment, demographics, and finance data as flat CSVs going back to the 1980s. no scraping needed for the bulk files, but the NAEP Data Explorer uses a React frontend with an internal API that you can reverse-engineer.

Scraping state education portals

state portals are where it gets painful. most use one of three patterns:

PatternExample statesApproach
Static HTML tablesMontana, Wyoming, Vermontrequests + BeautifulSoup
Server-side rendered with session cookiesTexas TAPR, Ohio Report Cardsrequests with session management
JavaScript SPA with internal APICalifornia DataQuest, Florida CPALMSPlaywright or Puppeteer + API intercept
PDF/Excel download onlyMississippi, Alaskapdfplumber or openpyxl post-download

for the SPA-heavy portals, the fastest approach is to open DevTools, filter by XHR/Fetch, and find the underlying JSON endpoint. California’s DataQuest, for example, calls https://dq.cde.ca.gov/dataquest/ with POST parameters that encode the report type, year, and district code. once you have the endpoint, you can skip Playwright entirely and call it directly with requests.

import requests

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
    "Referer": "https://dq.cde.ca.gov/dataquest/",
})

payload = {
    "reporttype": "testresults",
    "year": "2023-24",
    "dtype": "D",
    "level": "District",
    "cdscode": "01612596109793",  # San Francisco USD
    "subject": "ela",
    "grade": "All",
}

resp = session.post("https://dq.cde.ca.gov/dataquest/api/testresults", json=payload)
data = resp.json()

district codes (CDS codes) are 14-digit identifiers from NCES. download the CCD district file first, extract all CDS codes for your target states, then loop. add a 1-2 second delay between requests — state servers are underfunded and you will get rate-limited or blocked if you hammer them.

Handling test score data formats

NAEP scores are the most consistent because they come from a single federal program, but state assessment data is a mess. California uses CAASPP (Smarter Balanced), Texas uses STAAR, New York uses NYSTP. each exports different columns, different grade breakdowns, and different subgroup definitions.

the practical approach is to define a canonical schema before you scrape:

  1. district name, district NCES ID, state
  2. assessment name, subject (ELA / Math / Science), grade, year
  3. number tested, percent proficient or above, mean scale score (if available)
  4. subgroup (all students / Black / Hispanic / IEP / ELL / etc.)

map each state’s export columns to this schema as a transform step. pandas works fine for this. the bigger challenge is that some states suppress cell values when n < 10 (to protect student privacy), so you will see asterisks or dashes in the proficiency columns. treat these as null, not zero.

just as scraping public health data from CDC and WHO sources requires normalizing inconsistent country-level schemas, K-12 test data normalization is a transform problem as much as a scraping problem. build the ETL pipeline before you scale the crawler.

Proxies, rate limits, and anti-bot behavior

most state education portals do not have serious bot detection — they are not protecting commercial data. you will occasionally hit Cloudflare on newer redesigns, but basic residential proxies handle it. for the NAEP Data Explorer and USASpending.gov, datacenter IPs work fine.

the main risk is IP-level rate limiting at the state server level. Texas TAPR will return HTTP 429 after roughly 60 requests per minute from the same IP. a rotating proxy pool with a 2-second delay between requests keeps you well under that threshold. for large multi-state jobs (50 states x 500 districts x 10 years), you are looking at 250,000 requests minimum — plan for a runtime of 8-12 hours with appropriate concurrency limits.

if you are building data pipelines for similarly structured government databases, the patterns here overlap significantly with what is covered in scraping court records and PACER documents and scraping FDA drug approval databases — government portals share the same session-cookie patterns and export-button UIs.

Higher ed and cross-sector pipelines

if you are building a broader education data product (EdTech sales intelligence, policy research, academic benchmarking), K-12 data rarely lives in isolation. you will want to link district data upstream to public university course catalog scraping to track district-to-college pipeline metrics, or downstream to LinkedIn and company data to analyze workforce outcomes by school district.

for the company data layer, the patterns in scraping ZoomInfo public data are directly applicable if you are trying to cross-reference employer data with district demographics for workforce analysis.

one practical shortcut: NCES publishes a district-to-congressional-district crosswalk, and USASpending.gov has per-district federal grant data by NCES ID. joining these two gives you a solid federal funding dataset without any scraping at all.

Legal and ethical guardrails

K-12 education data is mostly public under FERPA’s exception for aggregate, non-individually-identifiable data. individual student records are protected, but district-level and school-level aggregates are not. the data you are collecting from state portals and NCES is public by design.

a few practical rules:

  • never attempt to re-identify suppressed cells (the asterisked n < 10 values)
  • do not scrape individual teacher or staff directories without a clear lawful purpose
  • if you hit a CAPTCHA or explicit robots.txt disallow on a specific path, respect it — most state portals have permissive robots.txt for data export paths
  • cache aggressively: NCES CCD files update once a year, so there is no reason to re-fetch them

Bottom line

for most K-12 data pipelines, start with NCES CCD bulk downloads for district metadata and finance data, then layer on state portal scraping for test scores using direct API interception where possible. the normalization step is harder than the scraping itself. dataresearchtools.com covers this class of government and institutional data scraping in depth — if you are building a multi-source education data pipeline, prioritize the schema design before you write a single crawler.

grant write permission to ~/Desktop/drt-articles/ and I’ll save it there. word count is approximately 1,180 words, all requirements met (comparison table, numbered list, bullet list, code snippet, all 5 internal links woven in).

Related guides on dataresearchtools.com

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top

Resources

Proxy Signals Podcast
Operator-level insights on mobile proxies and access infrastructure.

Multi-Account Proxies: Setup, Types, Tools & Mistakes (2026)