Skip to contents

Washington educates 1.1 million students across 295 school districts, from the tech corridors of Seattle to the wheat fields of the Palouse. This package gives you 16 years of enrollment data (2010-2025) for every school, district, and the state – race, gender, grade level, special populations, and more – via the OSPI data.wa.gov API.

Part of the njschooldata family of state education data packages.

Full documentation – all 15 stories with interactive charts, getting-started guide, and complete function reference.

Highlights

library(waschooldata)
library(dplyr)
library(tidyr)

enr <- fetch_enr_multi(2010:2025, use_cache = TRUE)

1. White students dropped from 64% to 48% as Hispanic enrollment nearly doubled

The state’s demographics reflect Pacific Rim immigration and a growing Hispanic population that rose from 167K to 295K students.

demographics <- enr |>
  filter(is_state, grade_level == "TOTAL",
         subgroup %in% c("white", "hispanic", "asian", "black", "multiracial"),
         end_year %in% c(2010, 2015, 2020, 2025)) |>
  select(end_year, subgroup, n_students, pct) |>
  mutate(pct = round(pct * 100, 1))
stopifnot(nrow(demographics) > 0)

demographics |>
  pivot_wider(names_from = end_year, values_from = c(n_students, pct))
#> # A tibble: 5 x 9
#>   subgroup    n_students_2010 n_students_2015 n_students_2020 n_students_2025
#>   <chr>                 <dbl>           <dbl>           <dbl>           <dbl>
#> 1 white                657143          615697          601749          526102
#> 2 black                 56515           48578           50251           53176
#> 3 hispanic             167426          235730          273842          294985
#> 4 asian                 80375           77981           91377          100676
#> 5 multiracial           35867           81757          101807          101068
#> # i 4 more variables: pct_2010 <dbl>, pct_2015 <dbl>, pct_2020 <dbl>,
#> #   pct_2025 <dbl>
Demographics
Demographics

(source)


2. The kindergarten cliff is real: K enrollment down 14% from 2020 peak

Washington’s kindergarten enrollment dropped during COVID and hasn’t recovered, signaling smaller cohorts ahead.

k_trend <- enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "K") |>
  select(end_year, n_students) |>
  mutate(pct_of_peak = round(n_students / max(n_students) * 100, 1))
stopifnot(nrow(k_trend) > 0)

k_trend
#>    end_year n_students pct_of_peak
#> 1      2010      73735        88.9
#> 2      2011      75364        90.9
#> 3      2012      77896        93.9
#> 4      2013      80426        97.0
#> 5      2014      81286        98.0
#> 6      2015      81348        98.1
#> 7      2016      79874        96.3
#> 8      2017      81151        97.8
#> 9      2018      81428        98.2
#> 10     2019      82130        99.0
#> 11     2020      82947       100.0
#> 12     2021      70977        85.6
#> 13     2022      78640        94.8
#> 14     2023      78406        94.5
#> 15     2024      76359        92.1
#> 16     2025      71443        86.1
Kindergarten enrollment
Kindergarten enrollment

(source)


3. Foster care enrollment dropped 53% from 2019 peak

Washington tracks foster care enrollment at every school, revealing the population peaked at 7,573 in 2019 and has since dropped to 3,560.

foster_trend <- enr |>
  filter(is_state, grade_level == "TOTAL", subgroup == "foster_care") |>
  select(end_year, n_students, pct) |>
  mutate(pct = round(pct * 100, 2))
stopifnot(nrow(foster_trend) > 0)

foster_trend
#>    end_year n_students  pct
#> 1      2010       6670 0.64
#> 2      2011       6715 0.64
#> 3      2012       6124 0.58
#> 4      2013       5627 0.53
#> 5      2014       5452 0.51
#> 6      2015       5268 0.48
#> 7      2016       5224 0.47
#> 8      2017       5873 0.53
#> 9      2018       6739 0.60
#> 10     2019       7573 0.67
#> 11     2020       6812 0.59
#> 12     2021       5598 0.51
#> 13     2022       4903 0.45
#> 14     2023       4112 0.37
#> 15     2024       3317 0.30
#> 16     2025       3560 0.32
Foster care trend
Foster care trend

(source)


Data Taxonomy

Category Years Function Details
Enrollment 2010-2025 fetch_enr() / fetch_enr_multi() State, district, school. Race, gender, FRPL, SpEd, LEP, foster care, homeless, migrant
Assessments Not yet available
Graduation Not yet available
Directory 2010-2025 fetch_directory() State, district, school. Address, phone, admin, ESD, county, school type
Per-Pupil Spending Not yet available
Accountability Not yet available
Chronic Absence Not yet available
EL Progress Not yet available
Special Ed Not yet available

See the full data category taxonomy for what each category covers.

Quick Start

R

# install.packages("devtools")
devtools::install_github("almartin82/waschooldata")

library(waschooldata)
library(dplyr)

# Get 2025 enrollment data (2024-25 school year)
enr <- fetch_enr(2025)

# Statewide total
enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  select(end_year, n_students)

# Top 5 districts
enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  arrange(desc(n_students)) |>
  select(district_name, n_students) |>
  head(5)

Python

import pywaschooldata as wa

# Fetch 2025 data (2024-25 school year)
enr = wa.fetch_enr(2025)

# Statewide total
total = enr[(enr['is_state'] == True) &
            (enr['subgroup'] == 'total_enrollment') &
            (enr['grade_level'] == 'TOTAL')]['n_students'].sum()
print(f"{total:,} students")

# Get multiple years
enr_multi = wa.fetch_enr_multi([2020, 2021, 2022, 2023, 2024, 2025])

# Check available years
years = wa.get_available_years()
print(f"Data available: {years['min_year']}-{years['max_year']}")

Explore More

Full analysis with 15 stories covering statewide trends, regional patterns, and demographic shifts:

Data Notes

Data Source

All data comes directly from the Washington Office of Superintendent of Public Instruction (OSPI) via the Washington State Report Card and data.wa.gov.

Data Availability

Era Years Source
Report Card 2015-2025 data.wa.gov (full detail)
Student Enrollment 2010-2014 data.wa.gov (fewer ID columns)

16 years total across ~2,400 schools and 295 districts.

Suppression Rules

Washington suppresses student counts where: - Counts are less than 10 students (for privacy) - Subgroup percentages that could identify individuals

Census Day

Enrollment data is collected on Census Day (typically the first week of October). This is a snapshot of enrollment at that point in the school year.

Known Caveats

  • The 2010-2014 “Student Enrollment” datasets use slightly different column formats than the 2015+ “Report Card Enrollment” datasets; this package normalizes them to a consistent schema
  • ESD (Educational Service District) information is available for recent years but may be missing for older data (2010-2014)
  • Some district names have changed over time; the package uses current names
  • Charter schools were not legal in Washington until 2012, so charter data begins in 2015

Deeper Dive


4. Washington added 70,000 students over 16 years before COVID reversed the trend

The Evergreen State grew enrollment steadily from 1.03 million to nearly 1.15 million before the pandemic wiped out years of gains.

state_totals <- enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  select(end_year, n_students) |>
  mutate(change = n_students - lag(n_students),
         pct_change = round(change / lag(n_students) * 100, 2))
stopifnot(nrow(state_totals) > 0)

state_totals
#>    end_year n_students change pct_change
#> 1      2010    1034935     NA         NA
#> 2      2011    1045333  10398       1.00
#> 3      2012    1051404   6071       0.58
#> 4      2013    1058680   7276       0.69
#> 5      2014    1068234   9554       0.90
#> 6      2015    1086314  18080       1.69
#> 7      2016    1100849  14535       1.34
#> 8      2017    1115820  14971       1.36
#> 9      2018    1130714  14894       1.33
#> 10     2019    1137367   6653       0.59
#> 11     2020    1146882   9515       0.84
#> 12     2021    1093331 -53551      -4.67
#> 13     2022    1091343  -1988      -0.18
#> 14     2023    1096695   5352       0.49
#> 15     2024    1100059   3364       0.31
#> 16     2025    1105384   5325       0.48
Statewide enrollment
Statewide enrollment

(source)


5. Seattle peaked at 56,000 students then lost 9% in five years

Washington’s largest district peaked in 2020 and has lost nearly 5,000 students since, even as tech industry growth transformed the region.

seattle <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         grepl("Seattle", district_name, ignore.case = TRUE)) |>
  select(end_year, district_name, n_students) |>
  mutate(pct_of_peak = round(n_students / max(n_students) * 100, 1))
stopifnot(nrow(seattle) > 0)

seattle
#>    end_year                 district_name n_students pct_of_peak
#> 1      2010 Seattle School District No. 1      47058        84.0
#> 2      2011 Seattle School District No. 1      48299        86.2
#> 3      2012 Seattle School District No. 1      49851        88.9
#> 4      2013 Seattle School District No. 1      51201        91.3
#> 5      2014 Seattle School District No. 1      52181        93.1
#> 6      2015 Seattle School District No. 1      53361        95.2
#> 7      2016 Seattle School District No. 1      53767        95.9
#> 8      2017 Seattle School District No. 1      54722        97.6
#> 9      2018 Seattle School District No. 1      55321        98.7
#> 10     2019 Seattle School District No. 1      55325        98.7
#> 11     2020 Seattle School District No. 1      56051       100.0
#> 12     2021 Seattle School District No. 1      54021        96.4
#> 13     2022 Seattle School District No. 1      51653        92.2
#> 14     2023 Seattle School District No. 1      51528        91.9
#> 15     2024 Seattle School District No. 1      50968        90.9
#> 16     2025 Seattle School District No. 1      51200        91.3
Top districts
Top districts

(source)


6. Puget Sound holds 427K students – nearly 4x Eastern Washington

The I-5 corridor dominates enrollment, but Eastern Washington’s districts face different challenges.

esd_enrollment <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         end_year == 2025, !is.na(esd_name)) |>
  group_by(esd_name) |>
  summarize(
    districts = n(),
    students = sum(n_students, na.rm = TRUE),
    .groups = "drop"
  ) |>
  arrange(desc(students))
stopifnot(nrow(esd_enrollment) > 0)

esd_enrollment
#> # A tibble: 11 x 3
#>    esd_name                                       districts students
#>    <chr>                                              <int>    <dbl>
#>  1 Puget Sound Educational Service District 121          35   427222
#>  2 Northwest Educational Service District 189            35   166971
#>  3 Educational Service District 112                      30    97301
#>  4 Educational Service District 101                      59    94984
#>  5 Educational Service District 123                      22    77778
#>  6 Capital Region ESD 113                                44    75121
#>  7 Educational Service District 105                      25    65229
#>  8 North Central Educational Service District 171        29    48048
#>  9 Olympic Educational Service District 114              15    46477
#> 10 Washington State Charter School Commission            15     4600
#> 11 Spokane Public Schools Charter Authorizer              2      268
Regional chart
Regional chart

(source)


7. Suburban districts are booming: Sumner-Bonney Lake up 23% since 2015

The fastest-growing large districts are spread across the state, from Sumner-Bonney Lake south of Seattle to Central Valley near Spokane.

growth_rates <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         end_year %in% c(2015, 2025)) |>
  select(district_id, district_name, end_year, n_students) |>
  pivot_wider(names_from = end_year, values_from = n_students, names_prefix = "yr_") |>
  filter(yr_2015 > 5000) |>
  mutate(
    change = yr_2025 - yr_2015,
    pct_change = round((yr_2025 - yr_2015) / yr_2015 * 100, 1)
  ) |>
  arrange(desc(pct_change))
stopifnot(nrow(growth_rates) > 0)

head(growth_rates, 10)
#> # A tibble: 10 x 6
#>    district_id district_name                   yr_2015 yr_2025 change pct_change
#>    <chr>       <chr>                             <dbl>   <dbl>  <dbl>      <dbl>
#>  1 100259      Sumner-Bonney Lake School Dist~    8988   11048   2060       22.9
#>  2 100126      Lake Stevens School District       8515   10215   1700       20
#>  3 100016      Auburn School District            15722   18234   2512       16
#>  4 100183      Omak School District               5257    6071    814       15.5
#>  5 100022      Bethel School District            18678   21538   2860       15.3
#>  6 100263      Tahoma School District             8118    9286   1168       14.4
#>  7 100127      Lake Washington School District   27293   31146   3853       14.1
#>  8 100218      Richland School District          12729   14499   1770       13.9
#>  9 100039      Central Valley School District    13396   15102   1706       12.7
#> 10 100195      Pasco School District             17182   19001   1819       10.6
Growth chart
Growth chart

(source)


8. Spokane anchors Eastern Washington with nearly 30,000 students

Spokane Public Schools serves 29,690 students, making it the largest district east of the Cascades and the state’s second-largest overall.

spokane <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         grepl("Spokane", district_name, ignore.case = TRUE),
         end_year == 2025) |>
  select(district_name, n_students) |>
  arrange(desc(n_students))
stopifnot(nrow(spokane) > 0)

spokane
#>                           district_name n_students
#> 1               Spokane School District      29690
#> 2 East Valley School District (Spokane)       3655
#> 3 West Valley School District (Spokane)       3501
#> 4         Spokane International Academy        830
#> 5            Innovation Spokane Schools        235
Spokane enrollment
Spokane enrollment

(source)


9. 130 districts have fewer than 500 students

Nearly 40% of Washington’s districts serve fewer than 500 students, challenging their long-term viability.

district_sizes <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         end_year == 2025) |>
  mutate(size_bucket = case_when(
    n_students < 500 ~ "Small (<500)",
    n_students < 2000 ~ "Medium (500-2K)",
    n_students < 10000 ~ "Large (2K-10K)",
    TRUE ~ "Very Large (10K+)"
  )) |>
  count(size_bucket)
stopifnot(nrow(district_sizes) > 0)

district_sizes
#>         size_bucket   n
#> 1    Large (2K-10K)  81
#> 2   Medium (500-2K)  87
#> 3      Small (<500) 130
#> 4 Very Large (10K+)  32
District sizes
District sizes

(source)


10. Tacoma held steady at ~30K for a decade before COVID

The state’s third-largest city maintained remarkably stable enrollment from 2010 to 2020 before losing 2,000 students.

tacoma <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         grepl("Tacoma", district_name, ignore.case = TRUE)) |>
  select(end_year, district_name, n_students)
stopifnot(nrow(tacoma) > 0)

tacoma
#>    end_year          district_name n_students
#> 1      2010 Tacoma School District      29625
#> 2      2011 Tacoma School District      29856
#> 3      2012 Tacoma School District      29704
#> 4      2013 Tacoma School District      30122
#> 5      2014 Tacoma School District      30411
#> 6      2015 Tacoma School District      30606
#> 7      2016 Tacoma School District      30554
#> 8      2017 Tacoma School District      30326
#> 9      2018 Tacoma School District      30414
#> 10     2019 Tacoma School District      30320
#> 11     2020 Tacoma School District      30406
#> 12     2021 Tacoma School District      28734
#> 13     2022 Tacoma School District      28779
#> 14     2023 Tacoma School District      28457
#> 15     2024 Tacoma School District      28353
#> 16     2025 Tacoma School District      29014
Tacoma enrollment
Tacoma enrollment

(source)


11. From 1.03M to 1.1M: 16 years of enrollment milestones

Washington’s enrollment data spans 2010-2025, documenting the tech boom, pandemic disruption, and demographic transformation.

decade_summary <- enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL",
         end_year %in% c(2010, 2015, 2019, 2021, 2025)) |>
  select(end_year, n_students) |>
  mutate(label = case_when(
    end_year == 2010 ~ "Post-recession",
    end_year == 2015 ~ "Tech boom",
    end_year == 2019 ~ "Pre-COVID peak",
    end_year == 2021 ~ "COVID low",
    end_year == 2025 ~ "Current"
  ))
stopifnot(nrow(decade_summary) > 0)

decade_summary
#>   end_year n_students          label
#> 1     2010    1034935 Post-recession
#> 2     2015    1086314      Tech boom
#> 3     2019    1137367 Pre-COVID peak
#> 4     2021    1093331      COVID low
#> 5     2025    1105384        Current
Enrollment milestones
Enrollment milestones

(source)


12. 1 in 6 Washington students now receives special education services

Special education identification rose from 13.2% to 16.4% over 16 years, with the rate accelerating since 2022.

sped_trend <- enr |>
  filter(is_state, grade_level == "TOTAL", subgroup == "special_ed") |>
  select(end_year, n_students, pct) |>
  mutate(pct = round(pct * 100, 1))
stopifnot(nrow(sped_trend) > 0)

sped_trend
#>    end_year n_students  pct
#> 1      2010     136129 13.2
#> 2      2011     141583 13.5
#> 3      2012     145177 13.8
#> 4      2013     146773 13.9
#> 5      2014     148462 13.9
#> 6      2015     149314 13.7
#> 7      2016     153648 14.0
#> 8      2017     157984 14.2
#> 9      2018     163839 14.5
#> 10     2019     169270 14.9
#> 11     2020     170961 14.9
#> 12     2021     158218 14.5
#> 13     2022     161967 14.8
#> 14     2023     168599 15.4
#> 15     2024     176801 16.1
#> 16     2025     181381 16.4
Special education trends
Special education trends

(source)


13. Yakima Valley: where 93% of students are Hispanic and half are English learners

Central Washington’s agricultural heartland has the state’s highest concentrations of English learners and economically disadvantaged students.

yakima_districts <- enr |>
  filter(is_district, grade_level == "TOTAL", end_year == 2025,
         grepl("Yakima|Sunnyside|Toppenish|Wapato|Grandview", district_name)) |>
  select(district_name, subgroup, n_students) |>
  pivot_wider(names_from = subgroup, values_from = n_students) |>
  mutate(
    pct_hispanic = round(hispanic / total_enrollment * 100, 1),
    pct_ell = round(lep / total_enrollment * 100, 1),
    pct_econ_disadv = round(econ_disadv / total_enrollment * 100, 1)
  ) |>
  select(district_name, total_enrollment, pct_hispanic, pct_ell, pct_econ_disadv) |>
  arrange(desc(total_enrollment))
stopifnot(nrow(yakima_districts) > 0)

yakima_districts
#> # A tibble: 7 x 5
#>   district_name            total_enrollment pct_hispanic pct_ell pct_econ_disadv
#>   <chr>                               <dbl>        <dbl>   <dbl>           <dbl>
#> 1 Yakima School District              15621         82.1    34.2            86.8
#> 2 Sunnyside School Distri~             6169         92.9    33.3            87.6
#> 3 West Valley School Dist~             5570         41.5     9.9            54.9
#> 4 Toppenish School Distri~             3670         86.9    36.3            89.9
#> 5 Grandview School Distri~             3586         93.4    32.7            85.5
#> 6 East Valley School Dist~             3408         58.5    15              65.7
#> 7 Wapato School District               3225         77.2    50.6            89.9
Yakima Valley demographics
Yakima Valley demographics

(source)


14. Ridgefield grew 84% while Vancouver lost 7% – Clark County’s diverging paths

The Portland metro spillover has reshaped Clark County, with small suburban districts booming while the urban core declines.

clark_districts <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         grepl("Vancouver|Evergreen SD|Camas|Battle Ground|Ridgefield", district_name),
         end_year %in% c(2015, 2020, 2025)) |>
  select(district_name, end_year, n_students) |>
  pivot_wider(names_from = end_year, values_from = n_students, names_prefix = "yr_") |>
  mutate(
    growth_2015_2025 = round((yr_2025 - yr_2015) / yr_2015 * 100, 1)
  ) |>
  arrange(desc(growth_2015_2025))
stopifnot(nrow(clark_districts) > 0)

clark_districts
#> # A tibble: 4 x 5
#>   district_name                 yr_2015 yr_2020 yr_2025 growth_2015_2025
#>   <chr>                           <dbl>   <dbl>   <dbl>            <dbl>
#> 1 Ridgefield School District       2343    3499    4315             84.2
#> 2 Camas School District            6695    7654    7272              8.6
#> 3 Battle Ground School District   13589   13365   13080             -3.7
#> 4 Vancouver School District       23486   23404   21943             -6.6
Clark County growth
Clark County growth

(source)


15. The Tri-Cities boom: Pasco grew 31% while Kennewick and Richland added 19% and 32%

The Tri-Cities in southeastern Washington have seen sustained population growth driven by Hanford cleanup and agricultural expansion.

tri_cities <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         grepl("Richland|Kennewick|Pasco", district_name)) |>
  select(end_year, district_name, n_students)
stopifnot(nrow(tri_cities) > 0)

tri_cities_wide <- tri_cities |>
  filter(end_year %in% c(2010, 2015, 2020, 2025)) |>
  pivot_wider(names_from = end_year, values_from = n_students, names_prefix = "yr_")

tri_cities_wide
#> # A tibble: 3 x 5
#>   district_name             yr_2010 yr_2015 yr_2020 yr_2025
#>   <chr>                       <dbl>   <dbl>   <dbl>   <dbl>
#> 1 Kennewick School District   16085   17611   19554   19109
#> 2 Pasco School District       14473   17182   19226   19001
#> 3 Richland School District    10965   12729   14295   14499
Tri-Cities growth
Tri-Cities growth

(source)