eCFR: Search US Federal Regulations, Parts & Amendments
Pricing
from $1.40 / 1,000 regulation row returneds
eCFR: Search US Federal Regulations, Parts & Amendments
Search the Code of Federal Regulations by phrase, title, part or agency and get sections as rows: citation, headings, matched excerpt, effective window and change types. Further modes list the parts and sections inside a title, amendment dates per section, and the title and agency dictionaries.
Pricing
from $1.40 / 1,000 regulation row returneds
Rating
0.0
(0)
Developer
Samat Makatov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Search the Code of Federal Regulations by phrase, title, part or agency and get sections as rows: citation, headings, matched excerpt, effective window and change types. Further modes list the parts and sections inside a title, amendment dates per section, and the title and agency dictionaries.
Every row comes from the government's own eCFR JSON API — no key, no proxy, no browser, no login. You get the
citation (21 CFR 820.10), the part and section headings, the matched passage, the dates a version
started and ends, whether it is in force, and the link to the official page; the amendment modes add the
amendment and issue dates of every recorded change. Built for compliance and quality teams, regulatory lawyers,
policy analysts and agents that need a citation with a link rather than a web page. It returns metadata, structure and
excerpts — not the full text of a section; see Limits & FAQ for why.
Use cases
- Watch the parts your product is regulated under. Run
searchwithlookbackDays: 7andonlyNew: trueon a schedule and the dataset holds only the sections that actually moved this week — with the date the new text took effect. - Prove when a rule last changed, for an audit.
versionson a title and part gives one row per recorded amendment withamendmentDate,issueDateand whether the change was substantive, so a finding gets a dated citation. - Build a table of contents for a RAG index.
structureon a title or part writes every subpart and section with its heading, the range it covers andsizeBytes, so you know how long each node is before you fetch anything. - Scope a topic before you read.
countsturns a phrase into a map of the code — how many matching sections sit in each title, chapter and part — for one request instead of thousands of paid rows. - Give an agent a citation tool. One
run-sync-get-dataset-itemscall answers "which section says this" with the citation, the heading and a link a human can open. - Keep a dated copy of the code for a contract.
asOfDatereads the code as it stood on a past day, and every row carries that day, so a quote in an agreement stays checkable later.
Input
Nothing is required: with no input at all the actor searches the whole code with the prefilled phrase and writes 50 rows.
| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
mode | string | search | search, structure, versions, counts, titles, agencies — see Modes |
query | string | — (prefill medical device) | Words to find in the regulation text; used by search and counts. Quote a phrase ("design controls") to keep the words together. Empty in search returns whatever the other filters allow |
order | string | relevance | relevance, newest, oldest, hierarchy — see Sort orders |
asOfDate | string | — | YYYY-MM-DD. Empty = the newest day the source has published (usually 1–3 days behind today). A future day is clamped down, not refused |
includeHistory | boolean | false | false = one row per section, the version in force on asOfDate. true = also the superseded and not-yet-effective versions |
changedAfter | string | — | YYYY-MM-DD. Keep only sections whose text was touched after this day |
changedBefore | string | — | YYYY-MM-DD, the other end of the change window |
lookbackDays | integer | — | 1–3650. Relative change window counted in UTC from the day the run starts. Ignored when changedAfter is set |
cfrTitle | integer | — (prefill 21) | 1–50, see CFR titles. Optional in search and counts, required by structure and versions, ignored by titles and agencies |
cfrChapter | string | — | Roman numeral as the code prints it (I, III, XII). Needs cfrTitle |
cfrPart | string | — | Part number, e.g. 820 in title 21 or 141 in title 40. Needs cfrTitle |
cfrSubpart | string | — | Subpart letter (A, C, UUUUU). Needs cfrPart |
cfrSection | string | — | A single section written as the citation does: 820.30, 141.23. The part is taken from it when cfrPart is empty |
agencySlugs | string[] | — | Agency slugs, combined with OR — see Agency slugs. A near miss is corrected, an unknown slug is refused |
nodeTypes | string[] | ["part","section"] | structure only: which levels become rows — chapter, subchapter, part, subpart, subjectGroup, section, appendix, title |
substantiveOnly | boolean | false | versions only: keep only amendments the source marks substantive |
includeRemoved | boolean | false | versions only: also write sections an amendment deleted, with removed: true |
onlyNew | boolean | false | Remember every row key in this actor's key-value store and write only keys no earlier run delivered |
maxItems | integer | 50 | 1–5000. The search index serves at most 10 000 hits per query, however deep you page |
fields | string[] | all | Keep only these fields, in this order, e.g. ["citation","sectionName","startsOn","url"] |
Reference
Modes
| Mode | Question it answers | Needs | Endpoint behind it |
|---|---|---|---|
search | Which sections of the code talk about this? | nothing | the search index over the codified text |
structure | What is inside this title or part? | cfrTitle | the title's tree for a given day |
versions | When was this last amended, and how often? | cfrTitle | the recorded amendment log |
counts | Where in the code is this topic regulated? | nothing | hit counts per title, chapter and part |
titles | Which titles exist and how current are they? | nothing | the title dictionary |
agencies | Which agency owns which chapter, and what is its slug? | nothing | the agency dictionary |
structure and versions read one title, so they are the two modes that need cfrTitle. titles and agencies need
no input at all — run them once, keep the values, and use them in the filters of the other modes.
Sort orders
| Value | Effect |
|---|---|
relevance | Best match for the phrase first (search) |
newest | Newest version first in search, newest amendment first in versions — the setting for a change feed |
oldest | Oldest first, for reading a section's history forward |
hierarchy | The order the code prints, by title, part and section — the setting for exporting a part |
structure always follows the code's own order, titles its numbering and agencies its alphabet.
CFR titles
The 50 titles are the top level of the code. The ones people ask for most:
| Title | Name | Typical use |
|---|---|---|
| 7 | Agriculture | food and farm programs |
| 12 | Banks and Banking | bank and credit-union rules |
| 14 | Aeronautics and Space | aviation |
| 17 | Commodity and Securities Exchanges | securities and derivatives |
| 21 | Food and Drugs | food, drugs, medical devices |
| 26 | Internal Revenue | tax regulations |
| 29 | Labor | employment and workplace safety |
| 40 | Protection of Environment | air, water, waste, chemicals |
| 45 | Public Welfare | health privacy, research ethics |
| 47 | Telecommunication | spectrum and telecom |
| 48 | Federal Acquisition Regulations System | government contracting |
| 49 | Transportation | rail, road, pipeline, hazmat |
Run { "mode": "titles" } for the full list with names and the day each title is current through — that is also the
honest answer to "how fresh is the text I am quoting".
Agency slugs
agencySlugs filters search by the chapters an agency owns, which is broader than one title and narrower than the
whole code. A few common ones:
| Slug | Agency | Chapters it owns include |
|---|---|---|
environmental-protection-agency | EPA | 40 CFR I, IV, VII |
food-and-drug-administration | FDA | 21 CFR I |
securities-and-exchange-commission | SEC | 17 CFR II |
occupational-safety-and-health-administration | OSHA | 29 CFR XVII |
federal-communications-commission | FCC | 47 CFR I |
internal-revenue-service | IRS | 26 CFR I |
federal-aviation-administration | FAA | 14 CFR I |
agriculture-department | USDA | 7 CFR XVI, XX, XXI |
Run { "mode": "agencies" } for all of them with the chapters each one writes and the sub-agencies below it. A slug
with a typo is corrected to the closest one and the correction is logged; a slug that resembles nothing is refused
with a message rather than answered with an empty run.
How citations and links are built
citation is assembled from the hierarchy of the node: 21 CFR 820.10 for a section, 40 CFR part 141 for a part,
21 CFR part 820 subpart A for a subpart, 40 CFR part 58, Appendix E to Part 58 for an appendix,
21 CFR chapter I, subchapter Hurl is the official page of the node, e.g.
https://www.ecfr.gov/current/title-21/chapter-I/subchapter-H/part-820/subpart-A/section-820.10. An appendix is linked
through its part and a subject group has no page of its own. Historical rows link the current page and are dated by
startsOn / endsOn.
Examples
Which codified FDA rules mention a topic
{ "mode": "search", "query": "quality management system", "cfrTitle": 21, "order": "relevance", "maxItems": 20 }
One agency's sections across the whole code, in the order the code prints them
{ "mode": "search", "query": "pfas", "agencySlugs": ["environmental-protection-agency"], "order": "hierarchy", "maxItems": 20 }
A weekly watch list of sections that changed (only what is new since the last run)
{ "mode": "search", "query": "safety", "lookbackDays": 7, "order": "newest", "onlyNew": true, "maxItems": 50 }
The table of contents of one part, for a RAG index
{ "mode": "structure", "cfrTitle": 21, "cfrPart": "820", "nodeTypes": ["subpart", "section"], "maxItems": 40 }
Every recorded amendment of a part, newest first
{ "mode": "versions", "cfrTitle": 40, "cfrPart": "141", "order": "newest", "substantiveOnly": true, "maxItems": 30 }
Where a phrase is regulated, before exporting any sections
{ "mode": "counts", "query": "artificial intelligence", "maxItems": 30 }
How a single section used to read
{ "mode": "search", "cfrTitle": 21, "cfrSection": "820.30", "includeHistory": true, "order": "oldest", "maxItems": 20 }
Output
One row per section version, tree node, amendment or dictionary entry. The first row of a real run with the default
input (mode: "search", query: "medical device", cfrTitle: 21, 50 rows in six seconds):
{"mode": "search","nodeType": "section","citation": "21 CFR 892.2020","titleNumber": 21,"titleName": "Food and Drugs","chapter": "I","subchapter": "H","part": "892","subpart": "B","subjectGroup": null,"section": "892.2020","appendix": null,"identifier": "892.2020","heading": "Medical image communications device.","hierarchyHeading": "§ 892.2020","chapterName": "Food and Drug Administration, Department of Health and Human Services","subchapterName": "Medical Devices","partName": "Radiology Devices","subpartName": "Diagnostic Devices","sectionName": "Medical image communications device.","excerpt": "Identification. A medical image communications device provides electronic transfer of medical image… image data between medical devices. It may include a physical communications medium, modems… image review software functionality for medical image processing and manipulation, such","score": 51.984,"startsOn": "2021-04-19","endsOn": null,"inForce": true,"changeTypes": ["effective"],"structureIndex": 82397,"reserved": false,"removed": false,"asOfDate": "2026-09-24","found": true,"url": "https://www.ecfr.gov/current/title-21/chapter-I/subchapter-H/part-892/subpart-B/section-892.2020","fetchedAt": "2026-09-27T20:58:29.940Z"}
Filled in every mode: mode, nodeType, citation, titleNumber, url, asOfDate, fetchedAt, found
(citation, titleNumber and url are null on an agency row that owns no chapter of the code, and on the single
found: false row a run writes when nothing matched).
| Field | Type | Meaning |
|---|---|---|
mode | string | The mode that produced the row |
nodeType | string | Level of the code: section, appendix, part, subpart, chapter, subchapter, subtitle, subjectGroup, title, agency, or notFound |
citation | string | The citation as it is written in practice, e.g. 21 CFR 820.10 |
titleNumber / titleName | number / string | CFR title of the row |
chapter, subchapter, part, subpart, subjectGroup, section, appendix | string | The hierarchy, level by level; null where the node has no such level |
identifier | string | The node's own identifier (820.10, A, I) |
heading / hierarchyHeading | string | The node's heading and its printed label (§ 820.10) |
chapterName, subchapterName, partName, subpartName, sectionName | string | Headings of the levels above and of the node itself |
excerpt | string | search: the passage the index matched, with the markup removed |
score | number | search: relevance of the match |
startsOn / endsOn | string | search: the day this version took effect and the day it stopped (null = still current) |
inForce | boolean | search: whether the version was in force on asOfDate (computed here, not read off endsOn) |
changeTypes | string[] | search: what kind of change produced this version, e.g. effective, initial |
structureIndex | number | The source's position index of the node |
reserved / removed | boolean | The node is reserved, or was removed by an amendment |
amendmentDate / issueDate / versionDate | string | versions: when the amendment was made, the issue it was published under, and the version's own date |
name / substantive | string / boolean | versions: the printed section name, and whether the change was substantive |
sizeBytes | number | structure: size of that node's text in the source's own XML — how long a part is before you read it |
descendantRange | string | structure: the sections a node covers, e.g. 141.1 – 141.905 |
volumes / receivedOn / childCount | array / string / number | structure: printed volumes, when the source received the text (UTC), and how many children the node has |
latestAmendedOn, latestIssueDate, upToDateAsOf | string | titles: last amendment, its issue date, and the day the title is current through |
slug, shortName, displayName, parentSlug, childSlugs | string / string[] | agencies: the slug the filter accepts, the names, the parent department and the sub-agencies |
cfrReferences / cfrTitles | array | agencies: the {title, chapter} pairs the agency writes, and the title numbers |
hitCount / maxScore / level | number / number / string | counts: matching sections under the node, best score, and the source's own level name |
asOfDate | string | The day the code was read as of — the same for every row of a run |
found | boolean | false on the one row a run writes when nothing matched |
url | string | Official page of the node |
fetchedAt | string | Fetch time, ISO 8601 UTC |
Dataset views: Sections (search), Title structure, Amendments, Dictionaries & hit counts. A SUMMARY
record in the run's key-value store repeats the filters, the resolved asOfDate, whether it was clamped, the total
number of matches, the request count and every warning.
Use it from code / agents
curl -X POST "https://api.apify.com/v2/acts/yadroo~ecfr-regulations/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"mode":"search","query":"quality management system","cfrTitle":21,"maxItems":20}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('yadroo/ecfr-regulations').call({ mode: 'versions', cfrTitle: 40, cfrPart: '141', maxItems: 30 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("yadroo/ecfr-regulations").call(run_input={"mode": "counts", "query": "artificial intelligence", "maxItems": 30})items = client.dataset(run["defaultDatasetId"]).list_items().items
MCP: add https://mcp.apify.com to Claude / Cursor / any MCP client and call the yadroo/ecfr-regulations tool with the same JSON input.
For agents: use counts first, search second. A phrase like "artificial intelligence" matches sections in a dozen
titles. One counts run costs a few dozen rows and tells the agent which titles and parts to look in; the follow-up
search then carries cfrTitle and cfrPart and pays for the sections that matter instead of paging blindly. Pass
fields to trim the row to what the model actually reads — ["citation","sectionName","excerpt","url"] is usually enough.
Pricing
Pay per event: $0.001 per run start + $0.002 per dataset row. The start event is charged on every run, including a
run that matches nothing and writes only the found: false row. Apify plan discounts apply to the per-row price:
−10 % on Bronze, −20 % on Silver, −30 % on Gold and above.
| Run | Rows | Cost at list price |
|---|---|---|
| The default input (50 sections for a phrase in one title) | 50 | $0.001 + 50 × $0.002 = $0.101 |
A part's table of contents (structure, one part) | 12 | $0.001 + 12 × $0.002 = $0.025 |
A topic map before searching (counts) | 30 | $0.001 + 30 × $0.002 = $0.061 |
A weekly watch that finds two changed sections (onlyNew) | 2 | $0.001 + 2 × $0.002 = $0.005 |
Compute is small next to that: no browser, and the runs behind this README finished in a few seconds each — a search is
two requests, a part's structure three. The actor asks for 512 MB because its heaviest job parses a whole title's tree:
title 40 is 9.4 MB of JSON and 30 311 nodes, and walking every one of them needs well under half that memory. Passing
cfrPart or cfrChapter cuts the subtree before it is walked, which is why exporting one part is the cheap case.
Limits & FAQ
- No full section text, and that is the source's rule, not a shortcut.
robots.txtof the eCFR disallows the two endpoints that serve rendered and raw section text for every crawler, so this actor does not read them. You get the citation, the full hierarchy, the headings, the matched excerpt, the version window, the amendment dates and the link to the official page — open the link (or quote the citation) when you need the wording itself. - The code is one to three days behind today. The source publishes the code up to a processed day, which every row
reports as
asOfDate;mode: "titles"shows it per title asupToDateAsOf. A date the source has not reached is clamped down to the newest available day, logged as a warning and flagged inSUMMARY.asOfDateClamped— it is not an error. - 10 000 hits per query. The search index refuses to page past that offset. A run that reaches the ceiling says so
in the status message and in
SUMMARY.resultWindowHit; narrow it withcfrTitle,cfrPart,agencySlugsor a change window. - Only the JSON API is read. The site's HTML pages answer a redirect to a different domain when they are requested
from a data-centre address, so this actor never fetches a page — it talks to
www.ecfr.gov/apionly. Links in the rows are for you to open in a browser. - A missing node gives a row, not silence. A part or section that does not exist on the chosen day, a reserved
title, or a filter combination with no data yields exactly one row with
found: falseand a heading that says what was missing. A section that a rewrite removed (21 CFR 820.30 after the February 2026 rewrite of part 820) has no current page, butmode: "versions"still has its amendment history. - Superseded versions need
includeHistory. By default a section appears once, as it stood onasOfDate. WithincludeHistory: trueyou get one row per version, each with its ownstartsOn,endsOnandinForce— which is how you diff a section over time. inForceis computed, not copied. A dated hit can still carry a non-nullendsOnwhen a later version already exists, so "in force" is worked out fromstartsOn,endsOnandasOfDaterather than read off the source.- No published rate limit, so the actor stays polite. Requests are sequential with a short pause, 429 and 5xx answers (the amendment log occasionally returns 502) are retried with backoff, and a run stops after 40 requests.
- Empty fields are the source's.
subpart,subchapterandsubjectGroupexist only where the code uses them;excerptandscoreonly insearch;sizeBytesanddescendantRangeonly instructure; one agency in the dictionary owns no chapter of the code at all. onlyNewkeeps one list per filter combination. Changing the query, the title or the part starts a new list, so the first run of a changed watch writes everything it finds. The keys live in this actor's own key-value store.- Licensing. The Code of Federal Regulations is a work of the US government and in the public domain; the actor adds the structure, the citations and the links.
Made by Yadroo. Sibling actors: federal-register-documents (the daily rules and notices behind these amendments), sec-edgar-filings, openfda-records, cisa-kev-vulnerabilities, bls-release-calendar.