GovInfo Scraper: Bills, Laws & Congressional Records avatar

GovInfo Scraper: Bills, Laws & Congressional Records

Pricing

from $0.56 / 1,000 document scrapeds

Go to Apify Store
GovInfo Scraper: Bills, Laws & Congressional Records

GovInfo Scraper: Bills, Laws & Congressional Records

Scrape GovInfo for bills, public laws, congressional reports, hearings and the Federal Register archive. Package metadata plus direct PDF and text links.

Pricing

from $0.56 / 1,000 document scrapeds

Rating

0.0

(0)

Developer

Arman Hossain

Arman Hossain

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

20 days ago

Last modified

Share

GovInfo Scraper: Bills, laws, hearings and the Federal Register, with direct PDF and full-text links, straight from the GPO's own API

GovInfo Scraper searches the U.S. Government Publishing Office's official repository and returns one structured row per document, congressional bills, enacted public laws, the daily Congressional Record, committee hearings and reports, the Federal Register, and federal court opinions.

Every row carries the package metadata plus direct, public links to the PDF and the full text, so you can pipe results straight into a document ingestion pipeline. Plain HTTP: no browser, no proxies, no login.

Agent skill: SKILL.md

https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/govinfo-documents-scraper.md

What you get

Output fieldMeaning
packageIdGovInfo's stable identifier, e.g. BILLS-119s5239is
collectionCollection code the document came from (BILLS, PLAW, CREC, …)
titleDocument title, the popular short title for bills
congressCongress number, e.g. 119
billNumber, billType, docVersion5239, s (senate bill), is (introduced in senate)
dateIssued, lastModifiedPublication date, and when GovInfo last revised the package
governmentAuthorIssuing bodies, e.g. ["Congress", "Senate"]
pdfUrlDirect PDF on www.govinfo.gov
textUrlDirect full-text HTML on www.govinfo.gov
detailsUrlHuman-readable GovInfo page for the package
summaryThe official long title, when includeDetails is on
scrapedAtRun timestamp

A RUN_SUMMARY record in the key-value store holds per-collection counts, remaining API budget, the filters used, and any collection that failed.

Which source this uses, and why

GovInfo exposes more than one search surface. Two of them are undocumented routes behind the website's own navigation: one returns only facet counts with no document records, the other is internal, undocumented and rejects anything it does not expect. This Actor uses neither.

It reads the documented public API published by the Government Publishing Office, which returns real document records with package IDs, titles, dates and download links. That route needs an API key, which is free and arrives by email in seconds, and it carries a far higher request budget than the undocumented ones. DEMO_KEY works out of the box so the Run button does something useful immediately.

Common use cases

Legislative tracking for policy teams. Watch bills and enacted laws in the current Congress and diff on packageId between runs.

{
"collections": ["BILLS", "PLAW"],
"congress": 119,
"fromDate": "2026-07-01",
"maxResults": 2000,
"apiKey": "YOUR_FREE_KEY"
}

Build a bill-monitoring alert product. Keyword-scoped, newest first, cheap enough to run hourly.

{
"collections": ["BILLS"],
"searchTerms": ["artificial intelligence", "algorithmic", "machine learning"],
"fromDate": "2026-01-01",
"maxResults": 500,
"apiKey": "YOUR_FREE_KEY"
}

Legal research corpora. Federal court opinions and committee hearings with direct text links, ready for a downstream ingest step.

{
"collections": ["USCOURTS", "CHRG"],
"searchTerms": ["antitrust"],
"fromDate": "2024-01-01",
"maxResults": 20000,
"apiKey": "YOUR_FREE_KEY"
}

Input

FieldTypeDefaultNotes
collectionsarray[]GovInfo collection codes. Each is a separate sweep.
congressinteger0Single Congress number. 119 = 2025-2026. 0 = all.
searchTermsarray[]Full-text terms, OR-combined. Multi-word entries become exact phrases.
fromDatestring""YYYY-MM-DD lower bound on publication date.
maxResultsinteger500Global cap across collections. 0 = no cap.
apiKeystringDEMO_KEYFree key from api.data.gov/signup. Stored as a secret.
includeDetailsbooleanfalseAdds summary (official long title). +1 request per document.

You need at least one of collections, searchTerms or congress. GovInfo holds over three million documents; an entirely unfiltered search is never what anyone wants, so the Actor refuses it with a clear message rather than starting one.

Which combinations make sense. collections + fromDate is the workhorse for scheduled monitoring, results come back newest first, so maxResults gives you the most recent N. searchTerms narrows within that, and terms are OR'd, so more terms means more results, not fewer. congress only applies to congressionally-numbered collections (BILLS, PLAW, CHRG, CRPT, CDOC); date-keyed ones like FR and USCOURTS will simply return nothing if you set it. includeDetails is the one expensive option, see the note under Limits.

Output example

{
"packageId": "BILLS-119s5239is",
"collection": "BILLS",
"title": "American Glove Act of 2026",
"congress": 119,
"billNumber": "5239",
"billType": "s",
"docVersion": "is",
"dateIssued": "2026-08-04",
"lastModified": "2026-08-05T13:37:47Z",
"governmentAuthor": ["Congress", "Senate"],
"pdfUrl": "https://www.govinfo.gov/content/pkg/BILLS-119s5239is/pdf/BILLS-119s5239is.pdf",
"textUrl": "https://www.govinfo.gov/content/pkg/BILLS-119s5239is/html/BILLS-119s5239is.htm",
"detailsUrl": "https://www.govinfo.gov/app/details/BILLS-119s5239is",
"summary": "To ensure that nitrile glove procurements comply with the requirements of the Make PPE in America Act, and for other purposes.",
"scrapedAt": "2026-08-06T12:00:00.000Z"
}

Note the split between title and summary: GovInfo's search index returns the popular short title (American Glove Act of 2026), while the package record holds the official long title. With includeDetails: false you get the short title and summary is null.

RUN_SUMMARY in the key-value store:

{
"sweepsRequested": 2,
"sweepsFailed": 0,
"failures": [],
"documentsSaved": 500,
"requestsUsed": 2,
"rateLimited": false,
"rateLimit": { "limit": 1000, "remaining": 998, "usingDemoKey": false },
"filters": {
"collections": ["BILLS", "PLAW"],
"congress": 119,
"searchTerms": ["climate"],
"fromDate": "2026-01-01",
"maxResults": 500,
"includeDetails": false
},
"finishedAt": "2026-08-06T12:00:06.114Z"
}

Limits and behaviour

  • DEMO_KEY is capped at 10 requests per hour. That is enough to see the Actor work and not much else. A free key from api.data.gov/signup raises it to 1000 requests/hour, arrives by email immediately, and asks for nothing but an address. Get one before your first real run.
  • Documents page at 1000 per request. So on a free key, one hour of budget is roughly a million documents, as long as includeDetails is off.
  • includeDetails costs one request per document. 500 documents with details on is 500 requests, half your hourly budget, for a field you may not need. It is off by default for exactly that reason.
  • Congress, bill type and bill number come free. GovInfo encodes them in the package ID (BILLS-119s5239is → 119th Congress, senate bill 5239, introduced-in-senate version), so the Actor parses them out rather than spending a request. Date-keyed collections such as CREC-2026-08-05 have no congress in the ID and report null.
  • The budget is read from every response. rate-limit headers and rate-limit headers are logged after each collection and written into RUN_SUMMARY.rateLimit. GovInfo does not send a reset timestamp; the window is hourly.
  • Exhaustion stops the run cleanly. On a 429 the Actor stops, keeps everything already saved, sets RUN_SUMMARY.rateLimited: true, and tells you where to get a bigger key.
  • A bad key fails fast. A 401/403 stops the run immediately rather than repeating the same rejection once per collection.
  • One failing collection never aborts the run. Errors land in RUN_SUMMARY.failures and the next collection starts. The Actor only throws if every sweep failed.
  • Transient errors are retried. 5xx gets three attempts with linear backoff.
  • Pagination is cursor-based. GovInfo uses an offsetMark cursor rather than page numbers, which is what makes deep result sets reachable at all. The Actor follows it and stops when the cursor stops advancing.
  • Public-record data only. Everything here is published by the U.S. Government Publishing Office for reuse; no authentication protects it and no commercial licence is required.

Finding a collection code

The code is the uppercase token in every GovInfo URL. Open a document on govinfo.gov and read the package ID:

Package ID you seeCollection codeWhat it is
BILLS-119s5239isBILLSCongressional bills
PLAW-119publ102PLAWEnacted public and private laws
CREC-2026-08-05CRECDaily Congressional Record
CHRG-119hhrg58123CHRGCommittee hearings
USCOURTS-ca9-20-12345USCOURTSFederal court opinions

The complete list of 42 collections is at https://api.govinfo.gov/collections?api_key=DEMO_KEY.

API example

curl -X POST "https://api.apify.com/v2/acts/arman-bd~govinfo-documents-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collections": ["BILLS", "PLAW"],
"congress": 119,
"searchTerms": ["climate", "clean energy"],
"fromDate": "2026-01-01",
"maxResults": 200,
"apiKey": "YOUR_GOVINFO_KEY"
}'

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/govinfo-documents-scraper').call({
collections: ['BILLS'],
congress: 119,
searchTerms: ['artificial intelligence'],
fromDate: '2026-01-01',
apiKey: 'YOUR_GOVINFO_KEY',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const doc of items) {
console.log(`${doc.dateIssued} ${doc.packageId.padEnd(22)} ${doc.title}`);
console.log(` text: ${doc.textUrl}`);
}

FAQ

Do I need a proxy? No. Proxy configuration is not required to run this Actor.

Do I need an account on GovInfo? No. You supply no credentials.

Can I run it without a key at all? Yes, on DEMO_KEY, which is what the Actor uses by default. It is shared across every anonymous caller and capped at 10 requests/hour, so treat it as a trial, not a plan.

Why doesn't it use the wssearch endpoint? Because it is not a document search. wssearch/rb/{collection} returns the browse navigation tree, Congress numbers and counts, no documents, and answers 405 to POST. wssearch/search is POST-only, undocumented, and rejects requests it does not recognise with an unhelpful 400. The documented api.govinfo.gov/search returns real records and is what a production Actor should depend on.

Why is summary null? Because includeDetails is off. GovInfo's search index does not return an abstract; the official long title lives on the package record, which costs an extra request per document to fetch.

Why did congress come back null? The document is from a date-keyed collection (FR, CREC, USCOURTS) whose package IDs carry a date instead of a Congress number.

What happens if GovInfo is unavailable? 5xx responses are retried three times, then that collection is recorded in RUN_SUMMARY.failures and the run continues with the next one.

Can I schedule it? Yes, it is designed for it. Set fromDate to the previous run's date and diff on packageId.

Can I integrate it with something else? Yes, Apify API, client libraries, webhooks, scheduled runs, dataset exports (JSON/CSV/Excel) or MCP. Output is structured JSON.