Skip to content

New York City Budget

Machine-readable, reconciled structured data extracted from the New York City Council's adopted budget documents — discretionary funding (Schedule C), reporting mandates (Terms & Conditions), capital changes (Section 254), and post-adoption Transparency Resolutions — for Fiscal Years 2025, 2026, and 2027, plus a historical backfill to FY2009 (see coverage note below).

Every dollar figure here was extracted deterministically from the Council's own PDFs and checked line by line against the documents' printed totals. The FY2027 discretionary schedule reconciles to the exact dollar: $655,764,999.

▶ Explore it live: the interactive NYC Council Discretionary Funding explorer (Schedule C, FY2015–FY2027) is published on GitHub Pages — no setup required. Source and build steps are in viz/.

Per-year processing manifest: code/PARSING.md records, for every fiscal year and document type, exactly which parser + invocation produces its CSVs and the reconciliation status. It is the authoritative "how do I regenerate FY_N_?" reference.


Built by BetaNYC

BetaNYC is New York's civic organization dedicated to improving lives through public interest technology, open data, and civic design. We build tools, train the public, and advocate for a more transparent, accountable, and participatory city government.

City budgets are among the most consequential public documents there are, and among the least usable — hundreds of pages of PDF tables that resist analysis. This project turns three years of them into clean, joinable data so journalists, researchers, community boards, and New Yorkers can actually ask questions of their city's spending.

Support open civic data: beta.nyc · donate · newsletter


Licensing

This repository has two kinds of content under two different terms:

  • Source documents (source/) are © The City of New York. They are official NYC Council adopted-budget publications, reproduced here as public records for transparency and analysis. All rights to those documents remain with the City of New York.
  • Software and derived data — the parser code in code/, the extracted CSVs in data/, and the analysis document — are released under the MIT License (see LICENSE). This code was built with Claude.

If you use the derived data, please attribute BetaNYC and link back to this repository, and cite the City of New York as the source of the underlying documents.


How this was made

Three Python parsers (in code/) read the PDF text layer and emit structured rows using regular expressions, with no hand transcription and no language-model reading of the numbers. Each Schedule C category total is reconciled against the document's own printed TOTAL line, so the data can be trusted or challenged against the source. The Schedule C parser derives its category list and council-member roster from each document, so it adapts to a new fiscal year automatically.

Repository layout

New-York-City-Budget/
├── README.md                                       ← you are here
├── Insights-NYC-Council-Discretionary-FY25-FY27.md ← narrative analysis
├── LICENSE                                         ← MIT, for the code + derived data
├── source/              ← official NYC Council documents, © City of New York
│   ├── FY08/ … FY27/    (Schedule C, Terms, Capital, transparency-resolutions/ per year — PDFs)
│   └── expense-funding-disclosure/  (Council RnD award-level expense spreadsheets, FY2013–FY2027)
├── data/                ← extracted, reconciled CSVs
│   ├── fy09/ … fy27/    (per year: schedule_c/, terms/, capital/, transparency-resolutions/
│   │   │                 — whichever document types exist and parse for that year)
│   │   ├── schedule_c/  discretionary expense funding
│   │   ├── terms/       Terms & Conditions (reporting mandates)
│   │   └── capital/     Section 254 capital changes
│   └── combined/        all-years roll-ups (built by code/build_combined.py)
├── code/                ← parser scripts + variants + validate_data.py (QA) + tests + PARSING.md + requirements.txt
├── mcp/                 ← prototype MCP server (see below)
└── viz/                 ← Schedule C funding visualization (see viz/README.md)

source/expense-funding-disclosure/ — Council RnD award-level expense data

Alongside the adopted-budget PDFs, the repo includes the NYC Council Research & Data division's expense funding disclosure spreadsheets — the Council's own machine-readable, award-level discretionary expense files, FY2013–FY2027, as published at rnd.council.nyc.gov/expense_funding (retrieved 2026-07-15). Because they are already tabular, they need no PDF text extraction.

They complement the parsed Schedule C data in two ways: they reach two years further back (FY2013–FY2014) and they carry fields the PDFs do not expose cleanly — a MOCS ID# (the Mayor's Office of Contract Services key, present FY2024+, joins to registered contracts and Checkbook spending), the grantee EIN and full mailing address (geocodable to council district), and a Cleared/Pending clearance status. In effect they are the live continuation of NYC Open Data's City Council Discretionary Funding dataset (4d7f-74pe), which stopped updating in April 2021. Provenance, per-file manifest, schema (16/17/18-column evolution), and data-quality notes are documented in source/expense-funding-disclosure/README.md.

mcp/ — prototype MCP server

mcp/ holds a prototype Model Context Protocol server (TypeScript + SQLite) that exposes this repo's data to MCP-capable AI clients as structured query tools — Schedule C awards (FY2015–FY2027), Terms & Conditions, §254 capital, the Transparency Resolutions (FY2010–FY2024 + FY2026), and the Legistar crosswalk. It reads the repo's own data/ tree directly (no copied snapshot) and builds a local, git-ignored SQLite index from it, so the query layer and the data always move together. Still a prototype — see mcp/README.md for tools, scope, and how to build and run it.

The data files

data/{year}/schedule_c/{year}_schedule_c_initiatives.csv — authoritative totals

One row per Council initiative; sums exactly to each category's printed TOTAL. category, agencies, initiative, amount

data/{year}/schedule_c/{year}_schedule_c_awards.csv — who got what

One row per designation to a named organization. category, initiative, award_type, member, organization, program, ein, amount, agency, purpose

  • award_type = member_item (an individual Council Member's local designation) or initiative_provider (a provider named collectively under a citywide initiative).
  • ein is the tax ID (digits only) — the reliable join key to IRS 990 / nonprofit data. Organization names are best-effort; a minority are imperfect. For 64 remaining rows the name is not merely imperfect: the row boundary was lost during extraction, so the row's amount may belong to a different organization than the one organization names. A further 140 rows carry purpose prose instead of a name. Both are flagged by code/validate_data.py (org_merged / org_prose) and listed per file in data/QA-REPORT.md. 5,450 cells were repaired on 2026-08-12/13 from the Council's own disclosure — see DATA-ANOMALIES.md §20 and §21.

data/{year}/schedule_c/{year}_appendix_*.csv

Detail breakouts with a purpose field: _a_aging (Aging Discretionary), _b_local (Local Initiatives, includes an agency column), _c_youth (Youth Discretionary). These are subsets of the main body re-sorted by funding stream — do not add them to the Schedule C total.

data/{year}/terms/{year}_terms_and_conditions.csv

item_number, agency_name, agency_code, units_of_appropriation, num_units, report_deadlines, coverage_period, condition_text

data/{year}/capital/{year}_capital_projects.csv

Section 254 capital changes. part, agency, budget_line, sub_id, boro, fy1, fy2, fy3, fy4, sponsor, title, building_code, school_codefy1 is the adoption year; fy2..fy4 are out-years; boro: M/X/K/Q/R.

  • FY2025, FY2026, and FY2027 use the "Capital Project Detail" (Council-additions) schedule, share this schema, and reconcile against printed agency subtotals and both TOTALS FOR ALL grand totals. FY2025 is now directly comparable to FY2026/FY2027 (parsed from the Council-version supporting-detail book; Part I $775M / 1327 projects, Part II non-city $158,992,000 / 181 projects). Part III (the non-city-by-entity cross-tab of Part II) is emitted to the sidecar fy25_capital_noncity_by_entity.csv.
  • The broader FY2025 "Appropriation Changes" resolution book (all executive-capital changes, ~$5.2B, NOT RECONCILABLE, adds an action column) is a different document type and is retained for provenance as fy25_capital_changes_appropriation.csv.

data/fy26/transparency-resolutions/

Post-adoption discretionary designations from the 10 FY2026 Transparency Resolutions (per-resolution resoNN_transparency_designations.csv files + a combined fy26_transparency_all.csv). Columns: resolution, date, chart, fiscal_year, action, source, council_member, organization, program, ein, amount, agency, agy_num, ua, purpose, flagsaction ∈ designate / rescind / purpose_change; rescissions carry negative amounts. These record money the adopted budget left "to be designated post-adoption" (e.g. the FY2026 AI Community Engagement $1M). No printed totals exist, so they are labeled NOT RECONCILABLE; the only internal check is that transfers (rescind + re-designate) net to zero.

data/combined/

all_years_initiatives.csv and all_years_awards.csv — the per-year files stacked with a leading year column for cross-year analysis. Each also carries two derived *_canonical columns (see the editorial note below).

⚑ Editorial note — consolidated names. Schedule C spells the same program differently across fiscal years (& vs and, an ALL-CAPS era vs Title Case, singular/plural, and outright renames such as Senior Services → Older Adult Services). To let a program be tracked over time, we made an editorial decision to consolidate these into canonical names — surfaced as the derived initiative_canonical and category_canonical columns (and used for the viz's Fund axis). The original source names are preserved verbatim in the initiative and category columns; nothing is overwritten. The category merges are human judgment calls, checked against the organizations funded under each name. The full mapping is auditable in initiative_name_crosswalk.csv and category_name_crosswalk.csv, and the rationale is in DATA-ANOMALIES.md #17–#18.

legistar_crosswalk.csv — links each budget source document to its NYC Council Legistar legislative record (matter number, adoption date, and detail-page URL), for FY2008–FY2027. One row per document. Columns: fiscal_year, document_type, local_file, legistar_matter_number, legistar_url, adoption_date, status, notes.

  • document_typeschedule_c, terms_conditions, capital_a, capital_b, transparency_reso_NN (NN = the within-year sequence number).
  • local_file is the repo-relative path to the source PDF (under source/FYnn/); it is blank for matter-only rows where the Legislation exists but no local document was downloaded. Source-relative paths are used (not data/) because FY2008–FY2024 are not yet parsed to structured CSVs — that PDF→CSV work is deferred; this crosswalk is the legislative-provenance index that lands first.
  • statusconfirmed (matter individually verified, including "positional" bracket-confirmations and "inferred exhibit" Contract-Budget rows — the qualifier is kept in notes), candidate (an anchor/earliest-in-sequence or an exhibit not confirmed as a standalone matter — deliberately not upgraded to confirmed), or not_located (no Legistar matter found, or a matter with no local file, or a genuine archival gap).
  • legistar_url is blank for the FY2015–FY2020 Transparency Resolutions, whose per-item Legistar IDs were not captured in the source research (resolve on demand from the matter number).
  • Built from the three research/2026-07-07-legistar-links-*.md docs (which carry the per-row Legistar citations and same-day corrections). Where those docs corrected an earlier row (e.g. FY2012 Capital A, FY2013/FY2018 Schedule C), the corrected value is used and the correction is recorded in notes.

Reconciliation status

Year Schedule C categories reconciled Note
FY2027 25 / 25 exact grand total $655,764,999
FY2026 24 / 25 exact Immigrant Services: the source PDF's own line items exceed its printed total by $800
FY2025 24 / 26 exact Education: the source PDF's own line items exceed its printed total by $50,000

The two "misses" are arithmetic inconsistencies inside the official PDFs, not extraction errors — the parser faithfully captured both the line items and the printed total, and they disagree in the source.

Historical coverage (FY2009–FY2024)

Beyond the flagship FY2025–FY2027 set, the repo now backfills earlier years. Full per-year, per-document-type detail (and the parser/invocation for each) is in code/PARSING.md; the headline:

  • Schedule C — reconciled for FY2015–FY2024 (FY2015 via the dedicated parse_schedule_c_fy15.py, reconciled 24/24; FY2016–FY2024 via parse_schedule_c.py) and FY2009–FY2014 (initiatives-only, via parse_schedule_c_legacy.py — the early-era documents carry no award-level EIN tables; FY2015 and later DO). FY2008 remains open (see PARSING.md).
  • §254 Capital (Capital Project Detail) — reconciled 23/23–32/32 for FY2020, FY2022, FY2023, FY2024 (via parse_capital_detail.py).
  • Terms & Conditions — extracted for FY2015–FY2024 (via parse_terms_legacy.py; T&C print no totals).
  • Transparency Resolutions — extracted for FY2010–FY2024 (no printed totals). Financial columns (EIN/amount/agency/date/action) are reliable in every year; organization/member/program text is low-confidence in the older glued-text-layer years (FY2010–FY2013), flagged per-year in each *_reconciliation.txt. FY2009 (scanned, no text layer) and FY2013 resolutions 07/10/11 (.doc) are blocked.

Capital (Section 254): FY2025 reconciles 30/30 agency subtotals plus both grand totals exactly (Part I $775M / 1327; Part II $158,992,000 / 181; Part III cross-tab 106/106 entities); FY2026 reconciles 31/31; FY2027 reconciles 24/26. (The separate FY2025 appropriation-changes book remains NOT RECONCILABLE by nature.) Transparency Resolutions: no printed totals (NOT RECONCILABLE); transfers net to zero as expected. See each *_reconciliation.txt for details.

Data QA: beyond per-file reconciliation, code/validate_data.py runs row-level and cross-file integrity checks (schema, EIN validity + per-year coverage, amount/sign sanity, fiscal-year integrity, duplicate detection, column-bleed heuristic, and a reconciliation roll-up) over the whole data/ tree and writes a dated data/QA-REPORT.md. Latest run: 0 hard failures, 100% EIN coverage on every EIN-bearing file. Details in code/PARSING.md.

Known limitations

  • Some initiative_provider award rows have imperfect organization names. Correction (2026-08-12): this line previously read "(EIN + amount are correct)". That is not true for all of them. In 64 remaining rows the extraction lost the row boundary, so the amount can belong to a different organization than the organization field names. 239 such rows were repaired on 2026-08-12/13. See DATA-ANOMALIES.md §20 and §21.
  • Award rows are now reconciled against the printed INITIATIVE amount (validate_data.py, soft advisory) — the first pass/fail target the award stream has ever had. The per-year *_reconciliation.txt files still check only the category summary against printed TOTAL lines.
  • Recovered data lives in data/recovered/, never merged into the per-year extracts, so nothing already published moves: schedule_c_absorbed_awards.csv (442 awards, $66,472,992 the parser absorbed and lost) and schedule_c_appendix_recovered.csv (26,127 appendix designations, $283,588,100, for the six years whose appendix streams came out empty). Both carry confidence and provenance columns.
  • 5,450 repairs across organization, EIN, initiative and purpose are recorded in data/combined/org_name_recovery_crosswalk.csv with the original value and the replacement, so every automated edit is auditable and reversible. See DATA-ANOMALIES.md §21.
  • Award rows are not reconciled against a printed total. The per-year *_reconciliation.txt files reconcile the category summary stream against the documents' printed TOTAL lines. The award table — the per-organization, per-EIN rows — is reported as a bare tally with no printed total to check it against, in every year. Award-level completeness is therefore not established by the reconciliation status shown above.
  • Borough delegations ("Brooklyn", "Queens", …) appear in the member column as collective sponsors.
  • FY2025 capital is now row-comparable to FY2026/FY2027 — parsed from the FY2025 Council-additions "Capital Project Detail" book (the counterpart to the FY2026/FY2027 books), it shares their schema and reconciles. (Earlier releases used the different "Appropriation Changes" resolution book, now retained separately as fy25_capital_changes_appropriation.csv; that book alone is not row-comparable.) Note Part II re-lists the non-city subset, so summing fy1 across both parts double-counts non-city projects — filter by part when aggregating, exactly as for FY2026/FY2027.
  • Transparency Resolutions have no printed totals to reconcile against (only the transfer net-out check); ~0.2% of rows have an imperfect organization name (EIN + amount are recoverable).
  • Category names differ across years (FY2025 has a standalone "Libraries" that later folds into "Cultural Organizations"). Normalize before comparing.

Reproduce or extend to a new year

Requires Python 3 with the packages in code/requirements.txt (pypdf, cryptography):

python code/parse_schedule_c.py <ScheduleC.pdf> --outdir data/fy28/schedule_c --prefix fy28
python code/parse_terms.py       <Terms.pdf>     --outdir data/fy28/terms      --prefix fy28
python code/parse_capital.py     <Capital.pdf>   --outdir data/fy28/capital     --prefix fy28 \
       --roster data/*/schedule_c/*_schedule_c_awards.csv

Always read the generated *_reconciliation.txt to confirm a parse before trusting a new year.

Earlier years and other document types use variant parsers (parse_schedule_c_legacy.py, parse_terms_legacy.py, parse_capital_detail.py, parse_transparency_reso.py) — the exact parser and invocation for each fiscal year is in code/PARSING.md. After regenerating any Schedule C year, rebuild the cross-year roll-ups with python code/build_combined.py.

How this relates to other NYC budget data sources

This repository is one piece of a larger NYC budget-data ecosystem. It is deliberately narrow: designation-level, who-got-what data from the Council's adopted budget — the organization, the sponsoring Council member, the amount, the implementing agency, and the recipient's EIN. It is not a source of citywide fiscal totals, revenue, or long-run spending trends. Here is where the neighbors fit.

Source What it's best for Overlap with this repo
This repo Council discretionary (Schedule C) awards, Terms & Conditions, Section 254 capital changes, Transparency Resolutions, and a Legistar crosswalk, at the organization/EIN level
NYC Independent Budget Office — Data Center The aggregate fiscal picture: citywide and agency-level expenditures and revenue (FY1980+), capital expenditures (since 1985), debt, headcount, education spending, tax data; plus IBO's fiscal analyses and budget-option reports None at the award level. IBO has no discretionary/Schedule C/member-item data. It is the fiscal context this repo's who-got-what data sits inside. Most of the Data Center is also on NYC Open Data under agency "NYC Independent Budget Office (IBO)."
NYC Open Data — City Council Discretionary Funding (4d7f-74pe) Award-level Council discretionary funding, FY2009–FY2021, Council-published Directly overlaps FY2015–FY2021. It stopped updating April 2021, so this repo is the machine-readable source for FY2022–FY2027 and adds source-reconciled totals plus Terms, Capital, Transparency, and Legistar provenance.
NYC Checkbook (Comptroller) Actual spending and registered contracts Complements this repo: join on EIN to ask whether a designation became a paid contract.
NYC Council Finance Division / OMB The primary source documents this repo parses This repo is the structured, reconciled extraction of those documents.

In short: IBO tells you what the City spends, raises, and owes in aggregate over decades; this repo tells you which organizations the Council funded, and how much, in the adopted budget. Neither IBO nor NYC Open Data (after FY2021) publishes the second thing as machine-readable data. That is the gap this repository fills. A detailed source-by-source crosswalk (including how this data can be joined to IBO's agency-level fiscal tables) is in research/2026-07-08-ibo-data-center-crosswalk.md.

A companion BetaNYC visualization turns this repo's Schedule C data into an interactive explorer — explore it live (source and build steps in viz/). It shares its toolkit (DataMade's Look at Cook) with BetaNYC's citywide expense-budget explorer, which visualizes the full ~$114B adopted/modified budget across all agencies — the aggregate fiscal side this repo deliberately does not cover.

Future work

  • Schedule C vs. actuals. Compare discretionary designations here against NYC Checkbook spending/contract data — do designations actually convert into paid contracts, and at what lag or drop-off rate?
  • Capital project lifecycle. Trace a Section 254 capital line from budget proposal through adoption (this repo) to actual payment and completion (Checkbook capital commitments) — an end-to-end view of how capital dollars move from planning to money spent.

See research/ for active and lodged scoping plans, including closing the FY2022–FY2024 gap between this repo's PDF-extracted years and NYC Open Data's FY2009–FY2021 historical archive.

AI use in this project

BetaNYC uses AI tools openly and with human accountability. The extraction, reconciliation, and analysis tooling in this repository was built by AI agents (Anthropic's Claude) working under the direction and review of BetaNYC staff.

One commitment about the data: the figures here are not AI-generated. Every dollar amount is extracted deterministically from the Council's own adopted-budget PDFs and checked line by line against the documents' printed totals — never inferred, never estimated by a model. The FY2027 discretionary schedule reconciles to the exact dollar ($655,764,999); where a year does not yet reconcile, that status is recorded honestly in code/PARSING.md and DATA-ANOMALIES.md rather than papered over.

Questions about our approach: hello@beta.nyc.

License

Two licenses, split by what the file is:

  • Code (code/, mcp/, viz/): MIT © 2026 BetaNYC — use and modify freely with attribution preserved. The mcp/ package is published to npm as @betanyc/nyc-budget-mcp under its own MIT license (mcp/package.json).
  • Data and documentation (data/, source/, research/, and the top-level *.md data references): Creative Commons Attribution-ShareAlike 4.0 — reuse and adapt with credit to BetaNYC, and share adaptations under the same license.

The underlying budget documents are public records of the City of New York; these licenses cover this compilation, its reconciliation, and its tooling.

Acknowledgments

  • A member of the NYC City Council Finance Division staff supplied the FY2025 Council-version §254 Supporting Detail Book and flagged the expense-disclosure spreadsheets, which made the reconciled FY2025 capital detail and the award-level expense data in this repo possible.

Source: NYC Council Finance Division, adopted budget Schedule C, Terms & Conditions, and Section 254 capital changes, FY2025–FY2027, council.nyc.gov. Structured and analyzed by BetaNYC.

About

Machine-readable, reconciled NYC Council adopted-budget data (Schedule C, Terms & Conditions, Capital) for FY2025-FY2027. Source docs © City of New York; code MIT, built with Claude.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

19 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages