Clean Air Act "major source" emission thresholds by pollutant and area classification
Whether a stationary source (a factory, plant, or facility) needs a federal Clean Air Act permit turns on whether its potential to emit crosses a tons-per-year (tpy) threshold -- and 'major source' is not one number but several, set by different regulations that do not agree. The Title V definition at 40 CFR 70.2 alone carries three overlapping tests: the section 112 hazardous-air-pollutant test (10 tpy of a single HAP, 25 tpy of any combination), the section 302 test (100 tpy of any air pollutant subject to regulation, with greenhouse gases counting only at 100,000 tpy CO2 equivalent), and the part D title I nonattainment test, tiered by pollutant (VOC, NOx, CO, PM-10) and by how severely out of attainment the area is (ozone precursors at 100 tpy in Marginal or Moderate areas, 50 in Serious, 25 in Severe, 10 in Extreme). PSD is a separate definition in a separate part -- 40 CFR 52.21(b)(1)(i) -- and it splits again: 100 tpy for the source categories the rule lists by name, 250 tpy for everything else. That last distinction is the one most often flattened: a facility told 'the threshold is 100 tons a year' is being given the Title V number, which is the wrong answer for any source outside the listed categories. Each record is one test/pollutant/classification combination and the threshold that test sets, quoted from the regulation that sets it. Answers 'what's the major-source threshold for VOC in a Severe ozone nonattainment area', 'does 25 tpy of a HAP make me major', and 'is my PSD threshold 100 or 250 tons a year'.
The data
| Row ID | Which major-source test | Pollutant or pollutant class | Area classification (if applicable) | Threshold (tons per year) | Definition heading |
|---|---|---|---|---|---|
| co-nonattainment-serious | Part D Title I nonattainment major stationary source | carbon monoxide | Serious | 50 | Major source means any stationary source |
| ozone-nonattainment-voc-nox-extreme | Part D Title I nonattainment major stationary source | volatile organic compounds or oxides of nitrogen | Extreme | 10 | Major source means any stationary source |
| ozone-nonattainment-voc-nox-marginal | Part D Title I nonattainment major stationary source | volatile organic compounds or oxides of nitrogen | Marginal | 100 | Major source means any stationary source |
| ozone-nonattainment-voc-nox-moderate | Part D Title I nonattainment major stationary source | volatile organic compounds or oxides of nitrogen | Moderate | 100 | Major source means any stationary source |
| ozone-nonattainment-voc-nox-serious | Part D Title I nonattainment major stationary source | volatile organic compounds or oxides of nitrogen | Serious | 50 | Major source means any stationary source |
| ozone-nonattainment-voc-nox-severe | Part D Title I nonattainment major stationary source | volatile organic compounds or oxides of nitrogen | Severe | 25 | Major source means any stationary source |
| ozone-transport-region-voc | Part D Title I nonattainment major stationary source | volatile organic compounds | ozone transport region | 50 | Major source means any stationary source |
| pm10-nonattainment-serious | Part D Title I nonattainment major stationary source | PM-10 | Serious | 70 | Major source means any stationary source |
| psd-any-other-source-250tpy | PSD major stationary source (40 CFR 52.21) — any other source category | a regulated NSR pollutant | 250 | Major stationary source means | |
| psd-listed-source-category-100tpy | PSD major stationary source (40 CFR 52.21) — one of the listed source categories | any regulated NSR pollutant | 100 | Major stationary source means | |
| section112-combined-hap | Section 112 HAP major source | any combination of such hazardous air pollutants | 25 | Major source means any stationary source | |
| section112-radionuclides | Section 112 HAP major source | radionuclides | specified by the Administrator by rule | Major source means any stationary source | |
| section112-single-hap | Section 112 HAP major source | any hazardous air pollutant which has been listed pursuant to section 112(b) of the Act | 10 | Major source means any stationary source | |
| section302-any-regulated-pollutant | Section 302 major stationary source (Title V, 40 CFR 70.2) | any air pollutant subject to regulation | 100 | Major source means any stationary source | |
| section302-ghg-co2e | Section 302 major stationary source (Title V, 40 CFR 70.2) — greenhouse-gas ‘subject to regulation’ threshold | Greenhouse gases (GHGs) | 100,000 | Major source means any stationary source |
Where this came from
Every record above links the page it was taken from and quotes the sentence that states it. These are the 2 sources this dataset was assembled from.
- ecfr.govhttps://www.ecfr.gov/current/title-40/chapter-I/subchapter-C/part-70/subpart-A/section-70.2
- ecfr.govhttps://www.ecfr.gov/current/title-40/chapter-I/subchapter-C/part-52/subpart-A/section-52.21
Machine-readable
- data.jsonThe whole dataset — every record with its source URL and source quote.
- Open Knowledge Format bundleOne JSON object per line — every record's frontmatter and quoted span exactly as it is held here, in one fetch.
- data.csvThe same records as one flat table, for a spreadsheet or a dataframe. The last four columns are the source URL, the quoted sentence it was read from, the date we last checked it, and which columns are our reading rather than the page's words.
- How this is made and checkedWhat "verified against source" does and does not mean.
From your own code
Same records, same quotes, without scraping the page: refsource is on PyPI and npm. Each value comes back carrying the URL it was read from and the sentence on that page that states it — .source and .quote sit on the value itself rather than in a side channel, so the checking step is available instead of skipped.
pip install refsource
refsource lookup clean-air-act-major-source-thresholds row_id=co-nonattainment-serious
npx -y refsource lookup clean-air-act-major-source-thresholds row_id=co-nonattainment-serious
Set your AI assistant up to use this
Two files and no account. Put this in .mcp.json at the root of your project — Claude Code, Cursor, Windsurf, VS Code and Codex all read that file — and your assistant can look this dataset up instead of recalling it. The server is remote, keyless and read-only.
{
"mcpServers": {
"referencesource": {
"type": "http",
"url": "https://referencesource.org/mcp"
}
}
}Add to Cursor · or, on the command line: claude mcp add --transport http referencesource https://referencesource.org/mcp --scope project
Then one line in the project's CLAUDE.md or AGENTS.md, so the assistant knows when to reach for it:
When a question needs "Clean Air Act "major source" emission thresholds by pollutant and area classification", call the referencesource MCP server at https://referencesource.org/mcp (tool `search_records`, dataset_slug `clean-air-act-major-source-thresholds`) instead of answering from memory — every record it returns carries its source URL and a verbatim quote from that page.What each tool does, and the servers built over single registers: Connect your AI assistant.