Florida Contractor License Scraper — DBPR Records
Pricing
$4.00 / 1,000 per license record returneds
Florida Contractor License Scraper — DBPR Records
Licensed Florida construction contractors from the official DBPR public records: name, full address, city, ZIP, license number and type, status, issue and expiry dates. 250,000+ licensees, or switch to the applicant file for phone numbers. Filter by license type, city or ZIP.
Pricing
$4.00 / 1,000 per license record returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
16 days ago
Last modified
Categories
Share
Licensed Florida construction contractors from the state's own public-records extracts: name, full street address, city, ZIP, license number and type, status, issue and expiry dates.
Certified general, building, roofing, plumbing, HVAC, pool and specialty contractors, plus business qualifiers. Filter by license type, city or ZIP.
Two record sets — pick the one you need
DBPR publishes these as separate files and they carry different fields. This Actor exposes both through one schema rather than silently merging them.
source | Rows | Has phone | Has license status & expiry |
|---|---|---|---|
licensed (default) — the contractor roster | 250,000+ | ❌ | ✅ |
applicants — license applicants | 104,359 | ✅ 76% | ❌ |
If you need to call people, use applicants. If you need verified license status, numbers and
renewal dates, use licensed. The roster genuinely contains no phone column — this Actor will not
pretend otherwise.
Example — licensed
{"source": "licensed", "isApplicant": false,"licenseNumber": "CBC006231","licenseTypeCode": "CBC","name": "WALTERS, DENNIS D","businessName": "BUILDING CONCEPTS OF TAMPA BAY, LLC","address1": "6635 GLENCOE DRIVE","city": "TAMPA", "state": "FL", "zip": "33617", "countyCode": "39","statusCode": "C", "status": "Current", "isCurrent": true,"effectiveDate": "2024-09-16","expirationDate": "2026-08-31", "daysUntilExpiry": 12}
Field fill — measured, not promised
Every record carries all 23 keys in both modes (a field the source does not have comes back null,
never missing). Counts below are from live runs on 2026-08-19: 3,414 licensed rows and 300
applicants rows. The roster file is ordered by license type, so the licensed sample is CBC and
CGC; where a field's fill differs sharply between the two, both numbers are given.
† QB (business qualifier) rows do not follow this table — see the section right below it.
| Field | licensed | applicants | Note |
|---|---|---|---|
name | 100% | 100% | roster stores LAST, FIRST M; applicants are joined FIRST MIDDLE LAST SUFFIX |
businessName | 72% | — | the DBA / qualifying company on the licence. Absent from the applicant file |
licenseNumber | 100% † | — | applicants have not been issued one yet |
licenseTypeCode | 100% | 100% | roster uses CBC; applicants use numeric 0605 |
licenseTypeName | — | 100% | the roster file ships the code only, no spelled-out name |
phone | — | 76% | the roster genuinely has no phone column; use applicants to call people |
address1 / city / zip | 98% | 98% | blank on the ~2% of records DBPR holds no address for |
countyCode | 96% | 98% | DBPR's numeric county code |
address2 | 7% | 8% | suite/apt line — sparse in the source itself, not a scraping gap |
statusCode / status / isCurrent | 100% | — | the applicant file carries no status column |
originalIssueDate | 86% | — | DBPR leaves it blank on older records — 98% of CBC, 67% of CGC |
effectiveDate / expirationDate / daysUntilExpiry | 100% † | — | " |
state, source, isApplicant, sourceUrl, scrapedAt | 100% | 100% |
Dashes are structural: those columns do not exist in that DBPR file. Verified 2026-08-18 by dumping every raw column of both extracts (22 columns in the roster, 15 in the applicant file).
QB (business qualifier) rows are a different animal — read this before you filter on QB
The licensed numbers above are measured on individual certified licences. QB rows are business
registrations, and DBPR's roster carries no licence number and no expiry for them. Measured
2026-08-20 on a 6,000-row run covering CAC CCC CFC CRC CPC SCC QB across Miami, Orlando, Tampa and
Jacksonville:
| Field | 6 certified types (n=1,701) | QB (n=4,299) |
|---|---|---|
licenseNumber | 100% (1,701 distinct) | 0% — DBPR issues none on these rows |
expirationDate / daysUntilExpiry | 100% | 0% — no renewal date in the file |
originalIssueDate | 98.7% | 100% |
effectiveDate | 99.9% | 100% |
businessName | 84.4% | 6.9% — on a QB row the company is in name |
address1 / city / zip / countyCode | 100% | 100% |
statusCode / status / isCurrent | 100% | 100% |
So: want licence numbers and renewal dates → do not include QB. Want the contracting companies
with a mailing address → QB is exactly the set you want, and the company name is in name.
(Coverage on CGC / CBC is the certified-type shape above, except originalIssueDate, which runs
98% on CBC and 67% on CGC — the 86% in the table.)
License type codes
QB business qualifier (a company registration — no licence number, no expiry) · CGC certified
general · CBC certified building · CAC air conditioning · CCC roofing · CFC plumbing ·
CRC residential · CPC pool · SCC specialty · FRO
(The applicant file uses numeric codes instead — 0605 = Certified General Contractor.)
Reliability note — why this needs a residential proxy
DBPR's download host sits behind Cloudflare, so this Actor needs a proxy — and the US country pin matters as much as the residential tier. Re-measured 2026-08-17, 12 fresh sessions per lane:
| Route | Result |
|---|---|
| No proxy / plain datacenter | 403 "Just a moment…" |
| Apify residential, no country pin | 2/12 — Cloudflare flags most of the pool |
Apify residential + US + pinned session | 12/12 · 200 text/csv |
The Actor defaults to RESIDENTIAL / United States with a fresh pinned session per request. It
pulls the 48 MB roster as six parallel HTTP Range chunks on six independent exit IPs (measured
7.1 s for the whole file, versus 15–55 s and one outright failure for a single whole-file GET), and
each chunk is retried on its own fresh exit — so one slow or blocked IP costs a single ~25 s chunk
retry instead of the whole run. If DBPR ever stops honouring Range, it falls back to a whole-file
GET that retries up to 8 times, each on a new exit. Leave the proxy country set to United States
unless you have a reason not to — dropping the pin is what makes downloads fail.
If Cloudflare happens to challenge every exit tried, the run ends successfully with zero records and a status message asking you to re-run — it never fails hard and you are never billed for rows you did not receive.
The Actor also sizes itself to whatever run timeout you set: it will not start a download it cannot
finish, and on a short timeout with a very large maxItems it returns partial data plus a status
message rather than being killed mid-write. The roster file is 48 MB, so if you want the whole
250,000-row set give the run at least 10 minutes. The unwalled sibling host www.myfloridalicense.com serves the search form but 404s
on these files.
What this Actor deliberately does not pull
cilb_certified.csv is 708 MB / ~4.1 million rows and looks like the obvious prize. It isn't a license
roster — it's the continuing-education transcript, one row per course per licensee, with the same
license number repeating dozens of times. Billing you per row for that would be billing you for
duplicates. cilb_registered.csv (28 MB) is the same shape. Neither is used.
Pricing
$0.004 per record ($4 per 1,000).
Public records published by the Florida Department of Business & Professional Regulation. You are responsible for complying with DBPR's terms and with how you use the data.