I built this actor; it's a paid tool on Apify with a free trial credit.
If you are a prime contractor writing a federal bid, sooner or later you need small business subcontractors: a machine shop for the parts, a woman-owned firm for the subcontracting plan, a HUBZone partner for the set-aside. The US Small Business Administration keeps the list. It is called SBA Small Business Search (the old Dynamic Small Business Search, DSBS), and every firm in it registered in SAM.gov and chose to be found by federal buyers.
The website is fine for looking up one company. It is slow for the real question: "which machine shops in Ohio could I put on this bid next week?". That needs the whole list in a table, plus a few filters the search page does not do for you.
I built SBA Small Business Search Scraper to return those profiles as clean JSON rows. This post takes 20 real "cnc machining" results from Ohio (run on 9 November 2026) and turns them into a shortlist.
Limits first: there are no contact person names, no revenue, no employee counts and no contract award history. E-mails come out only when they sit on the business's own domain; gmail-style mailboxes are dropped because they are often a person's private address.
Step 1: pull the list
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("rel8ble/sba-small-business-search-scraper").call(run_input={
"searchTerm": "cnc machining",
"states": ["Ohio"],
"maxResults": 20,
})
firms = client.dataset(run["defaultDatasetId"]).list_items().items
print(len(firms), "firms")
Each row has the legal name, UEI, CAGE code, NAICS codes, SBA certifications with dates, self-certifications from SAM.gov, quality standards, capabilities text, website, business e-mail, phone, address, year established, SAM status and the date the profile was last updated.
What the 20 rows looked like:
| field | rows |
|---|---|
| SAM.gov registration active | 17 |
| lists ISO 9000 | 11 |
| lists MIL-STD-45662A | 3 |
| profile updated in the last 12 months | 17 |
| profile updated in the last 3 months | 9 |
| business e-mail / phone / website | 19 / 19 / 16 |
| exporter | 4 |
| any active SBA certification | 1 |
Primary NAICS was mostly 332710 (machine shops, 6 firms) and 332721 (precision turned products, 3). The oldest shop was founded in 1945, the newest in 2025, median 1992.
Step 2: drop the firms you cannot name on a bid
Three filters do most of the work:
- Active SAM.gov registration. An expired registration means the firm cannot receive a federal award today. 3 of 20 were expired.
- A quality standard. A prime buying machined parts usually wants ISO 9000 or a MIL standard on file.
- A recent profile. A profile untouched for years is a hint the firm is not chasing federal work any more.
from datetime import date, timedelta
cutoff = (date(2026, 11, 10) - timedelta(days=365)).isoformat()
shortlist = [
f for f in firms
if f["samRegistration"] == "active"
and f["qualityStandards"]
and (f["lastUpdated"] or "") >= cutoff
and f["email"]
]
for f in sorted(shortlist, key=lambda f: f["lastUpdated"], reverse=True):
print(f'{f["name"]:<35} {f["city"]:<14} {f["primaryNaics"]} '
f'{"+".join(f["qualityStandards"]):<45} {f["lastUpdated"][:10]}')
That left 10 of 20. The top of the list, newest profile first:
| business | city | primary NAICS | quality standards | founded | profile updated |
|---|---|---|---|---|---|
| MARKLEY ENTERPRISES LLC | Cincinnati | 332710 | ISO 9000 | 1999 | 2026-10-16 |
| UNITED METAL FABRICATORS, INC. | Maple Heights | 332996 | ISO 9000 | 1945 | 2026-10-16 |
| SOLMET TECHNOLOGIES, INC. | Canton | 332721 | ISO 9000 | 1985 | 2026-10-09 |
| TWO M PRECISION CO. INC. | Willoughby | 332721 | ISO 9000 | 1977 | 2026-10-07 |
| UNITED TITANIUM, LLC | Wooster | 332722 | ISO 9000, MIL-Q-9858, MIL-STD-45662A | 2025 | 2026-09-29 |
| UNITED TOOL & MACHINE INC | Lakeview | 336390 | ISO 9000, MIL-Q-9858, MIL-STD-45662A | 1973 | 2026-07-22 |
Ten real candidates from one search, each with a CAGE code you can check in SAM.gov before you call.
Step 3: watch the certification trap
This part surprised me. Six of the 20 firms self-certified in SAM.gov as woman-owned, veteran-owned, service-disabled veteran-owned or small disadvantaged. Only one firm had an active SBA certification (VOSB and SDVOSB), and that firm's SAM.gov registration had expired.
Self-certification and SBA certification are not the same thing. Since 2024, SDVOSB set-asides need SBA certification, not just the SAM.gov checkbox, and 8(a), HUBZone and WOSB set-asides have always needed the SBA program status. If your plan counts on a certified partner, filter on sbaCertifications, not selfCertifications, and check the SAM status on the same row:
certified = [
f for f in firms
if f["sbaCertifications"] and f["samRegistration"] == "active"
]
print(len(certified), "certified and able to receive awards")
On this sample it prints 0. To find certified partners, put the certification in the search input instead of filtering afterwards:
run = client.actor("rel8ble/sba-small-business-search-scraper").call(run_input={
"naicsCodes": ["332710", "332721"],
"states": ["OH", "Michigan", "Indiana"],
"sbaCertifications": ["HUBZone", "SDVOSB"],
"activeSamOnly": True,
"onlyWithEmail": True,
"maxResults": 0,
})
activeSamOnly and onlyWithEmail run before the row is saved, so you do not pay for rows you would throw away.
How it works
SBA Small Business Search is a single-page app on top of a public JSON search API. The actor sends one search request to that API over plain HTTP, with no browser and no login, reads the answer as a stream and flattens each record into a row as it arrives. A few things from building it:
-
State and certification names must match the SBA's own spelling. The actor accepts
OHorOhioand maps it; an unknown value stops the run with an input error before anything is charged. - WOSB includes EDWOSB. The SBA search treats them as one family, so asking for WOSB also returns EDWOSB firms.
-
E-mails are filtered for privacy. Free and ISP mailboxes become
null;onlyWithEmailcounts only the e-mails that pass.
The 20-row demo took 3.2 s in an Apify cloud run.
Price and caveats
$0.80 per 1,000 rows, no start fee. Searches that find nothing, input errors and failed requests are not charged. The 20-row list above costs under two cents.
The data is what each business entered into SAM.gov and the SBA profile, so a capability line is a claim, not a verified fact. Check the SAM.gov entity record before you name anyone on a bid. The actor is not affiliated with or endorsed by the US Small Business Administration.
Actor page: https://apify.com/rel8ble/sba-small-business-search-scraper
Need a custom scraper or a ready dataset? Hire me on Fiverr: https://www.fiverr.com/rel8ble
Top comments (0)