NAIC SBS Insurance Producer Scraper avatar

NAIC SBS Insurance Producer Scraper

Pricing

Pay per usage

Go to Apify Store
NAIC SBS Insurance Producer Scraper

NAIC SBS Insurance Producer Scraper

Look up and bulk-export insurance producer and licensee records from the NAIC State Based Systems public lookup. Covers all 34 SBS jurisdictions, individuals and business entities, and all license statuses including expired, revoked and cancelled.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Gufran

Gufran

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 hours ago

Last modified

Categories

Share

Look up insurance producers, agents and agencies licensed across the NAIC State Based Systems (SBS) — the official registry used by 34 US states, the District of Columbia, Guam, Puerto Rico and the US Virgin Islands.

Three jobs, one Actor:

JobModeRequests
Verify one licence — "is this agent actually licensed, and for what?"targeted with an NPN or licence number1
Find a producer — "every S-* producer in New Jersey"targeted with a name1–15
Bulk export — "every producer and agency in Delaware"enumeratehundreds

Coverage

JurisdictionsAll 34 SBS participants
IndividualsYes — producers, agents, brokers
Business entitiesYes — agencies, brokerages
Licence statusesAll 14 — active, expired, revoked, cancelled, suspended, denied and more
Full detailOptional — emails, websites, LOA qualifications, CE compliance, appointments

The problem this Actor solves

Most NAIC scrapers quietly lose data. Here's why, and what this one does instead.

The NAIC search API returns a bare JSON array with no pagination and a hard cap of 25 rows per query. It just truncates. NAIC's own website can't tell you the total either — it shows a warning that 25 results were returned, and that's all.

The usual workaround, searching single letters, still breaks. Last name S, first name J in New Jersey returns exactly 25 rows — and rows 26 onward are gone, with no error.

This Actor treats a full page as "there is more behind this". It splits that query into finer partitions, re-runs each one, and repeats until nothing comes back truncated:

"S" -> 25 rows (truncated) -> split into "SA" "SB" "SC" ...
"SB" -> 8 rows (complete) -> done
"SA" -> 25 rows (truncated) -> split further

When a partition is still capped at maximum depth and cannot be split again, the Actor writes that exact prefix to a gaps list in its key-value store. You always know what was missed. Nothing disappears quietly.


Quick start

1. Verify one producer by NPN — 1 request

The fastest path. An NPN is a unique national identifier.

{ "jurisdictions": ["NJ"], "npn": 19623468, "enrichDetail": true }

2. Find producers by name

{ "jurisdictions": ["NJ"], "searchMode": "targeted", "lastName": "Smith" }

3. Export a whole jurisdiction

{
"jurisdictions": ["DE"],
"searchMode": "enumerate",
"entityTypes": ["IND", "ENT"],
"maxResults": 15000
}

4. Everyone in one state who is not currently licensed

Compliance and lead-gen use case — licences that lapsed, were revoked, or were surrendered.

{
"jurisdictions": ["NJ"],
"searchMode": "targeted",
"lastName": "A",
"licenseStatuses": ["CA", "REV", "EX", "SUS"]
}

Choosing a mode

Use targeted (default) whenever you have a concrete filter — a name, an NPN, a licence number, a city, a zipcode. It is 1 to 15 requests and finishes in seconds.

Use enumerate only when you want a whole population. It walks the name space letter by letter, subdividing wherever it hits the cap. Expect hundreds or thousands of requests, and a runtime measured in minutes.

You wantMode
One specific persontargeted
Everyone matching a name prefixtargeted with lastName
Every licence in a stateenumerate
Only revoked/expired licencestargeted + licenseStatuses
Producers in one citytargeted + businessCity

How a run actually executes

Understanding this helps you pick sensible limits.

targeted — one API call per (jurisdiction × entity type × licence status). If you supply an NPN or licence number, that collapses to a single call regardless of how many statuses exist, because those identifiers are unique.

enumerate — starts with 26 partitions, one per last-name initial, per jurisdiction × entity type × status. Any partition returning a full 25-row page is subdivided and re-queued. The crawl converges until nothing truncates.

While it runs, the status line updates every 50 queries:

250 queries done - 120 unique licensees collected - 0 unresolved gap(s).

Duplicate licencees are detected and never charged twice, and maxResults is a hard cap — the Actor stops producing the moment it's reached.

Measured behaviour

Real runs of this Actor, so you can size your expectations:

RunRecordsWall timePlatform cost
NPN lookup + full detail1~10 s$0.004
targeted name, 10 records10~15 s$0.003
enumerate NJ, 500 records500~60 s$0.024

Cost per record works out to roughly $0.00005–$0.00009, dominated by request-queue writes from subdivision rather than compute.


Input reference

Scope

FieldTypeDefaultWhat it does
jurisdictionsarray["NJ"]Two-letter SBS codes, or ALL for all 34.
searchModestringtargetedtargeted = answer a question. enumerate = collect a population.
entityTypesarray["IND"]IND individual producers, ENT agencies and brokerages. Add both for full coverage.
licenseStatusesarray[] = allLeave empty to include every status. A active, B approved-not-active, CA cancelled, EX expired, IN inactive, REV revoked, SUS suspended, DEN denied, and others. Codes vary slightly by state.
licenseTypeCodesarray[] = autoUsually leave empty — the Actor detects each state's producer code. Common: PRO, PAJ public adjuster, TPA.
loaTypesarray[] = allOptional filter. LLA accident & health, LLL life, LLC casualty, LLP property.

Search criteria — targeted mode only

Leave every field in this group empty when using enumerate.

FieldTypeWhat it does
lastNamestringMatches from the start of the name. Prefix match, not exact.
firstNamestringPrefix match.
dbaLastNamestringSearches assumed / trading names rather than the legal name.
npnintegerExact National Producer Number. Fastest single lookup.
licenseNumberintegerExact licence number.
feinstringFederal Employer Identification Number.
businessCitystringCity of the business address.
businessStatestringState or province of the business address.
businessZipcodestringZipcode of the business address.
mailingCountystringCounty of the mailing address.
residentLicensestringYes for residents only, No for non-residents, empty for both.

Output

FieldTypeDefaultWhat it does
enrichDetailbooleanfalseAdds ~8 extra requests per record and returns emails, websites, a structured address, per-line qualification and exam dates, CE compliance, appointments, branch offices and the NAIC internal licence id. Off by default because it multiplies cost.
maxResultsinteger1000Hard cap on unique licencees. The run stops the moment it's reached.
maxRequestsinteger5000Hard ceiling on upstream API calls. In enumerate mode you can hit this before maxResults, because subdivision costs requests.
concurrencyinteger8Parallel requests. Start here; raise only if a run feels slow.

Proxy

FieldTypeDefaultWhat it does
useProxybooleantrueRoutes through Apify Proxy. Recommended for bulk runs. Turn it off for a one-off lookup to shave the cost — direct requests work unless NAIC answers 403.
proxyConfigurationobject{ "useApifyProxy": true }Advanced proxy settings. The group is deliberately left unset so Apify picks the cheapest one your plan includes. Don't pin a group you aren't entitled to — naming an unavailable one (e.g. SHARED_DATACENTER, a paid add-on) makes the run fail immediately.
proxyCountrystringUSProxy exit country.
resumebooleantrueReuse the checkpoint so an interrupted run continues instead of re-charging for records already collected.

Proxy cost, measured on a 10-record run: $0.0026 with the default, $0.0025 with the proxy off, $0.0047 if you force residential. Residential is billed at roughly 4x the datacenter rate and this API does not need it — reach for it only if you hit repeated 403s.


Output

One dataset item per unique licensee. Empty values are "", never missing.

{
"licenseNumber": "3003526706",
"naicLicenseId": null,
"name": "AACH, CAYLEIGH JACLYN",
"lastName": "AACH",
"firstName": "CAYLEIGH",
"middleName": "JACLYN",
"licenseType": "Insurance Producer-Active",
"licenseTypeCode": "PRO",
"licenseStatus": "Active",
"licenseEffectiveDate": "02/26/2025",
"licenseExpirationDate": "04/30/2027",
"linesOfAuthority": [
{ "line": "Accident & Health or Sickness", "grantedOn": "02/26/2025" },
{ "line": "Casualty", "grantedOn": "02/26/2025" },
{ "line": "Life", "grantedOn": "02/26/2025" },
{ "line": "Property", "grantedOn": "02/26/2025" }
],
"naicProducerNumber": "19623468",
"residentLicense": "No",
"businessAddress": "BOYERTOWN, PA 19512",
"businessAddressCity": "BOYERTOWN",
"businessAddressState": "PA",
"businessAddressZipcode": "19512",
"businessPhone": "(610) 573-7339",
"businessPhoneRaw": null,
"fein": "",
"dbaName": "",
"designatedHomeState": "",
"entityType": "IND",
"jurisdiction": "NJ",
"jurisdictionName": "New Jersey",
"email": null,
"sourceUrl": "https://external-lookup-web.prod.naic.org/solar-external-lookup/lookup/licensee/summary/3003526706?jurisdiction=NJ&entityType=IND&licenseType=PRO",
"licenseManagerUrl": "https://external-lookup-web.prod.naic.org/solar-external-lookup/license-manager?entityType=IND&licenseNumber=3003526706&lastName=AACH&jurisdiction=NJ",
"detail": null,
"scrapedAt": "2026-10-02T15:23:50.531Z"
}
FieldNotes
licenseNumberThe state licence number as issued.
naicLicenseIdNAIC's internal id. Only set when enrichDetail is on.
name / lastName / firstName / middleNameRaw name plus parsed components.
licenseTypeCombined type and status, e.g. Insurance Producer-Active.
licenseStatusJust the status: Active, Expired, Revoked, Cancelled…
linesOfAuthorityEvery line held, each with the date it was granted.
naicProducerNumberThe NPN.
residentLicenseYes or No.
businessAddress*Pre-split into city / state / zipcode, so you don't have to parse it.
businessPhoneFormatted (XXX) XXX-XXXX.
emailOnly with enrichDetail.
sourceUrlDirect link to the official NAIC licensee page.
licenseManagerUrlDirect link to the state's licence manager portal.
detailOnly with enrichDetail. Contains licenses, dbaNames, per-line linesOfAuthority (with qualification, schoolCode, examCertDate, lineStatus), emails, phones, urls, demographics, continuingEducation, appointments, branchOffices, drlp, businessEntityAffiliations, and a detailErrors list if any sub-resource failed.

Resuming an interrupted run

Every run writes a CHECKPOINT_naic-sbs record to the key-value store holding the licence numbers already collected, the partitions already completed, and any unresolved gaps.

Re-running the same input picks up where it left off. Completed partitions aren't re-run and already-collected licencees aren't charged again, so a resumed run only seeds what's missing. Keep resume: true (the default) if you expect long enumerations to get interrupted.


Troubleshooting

No results for a state I expected data from. California, Texas, Florida, New York, Pennsylvania, Ohio, Georgia, Michigan and Washington license through their own separate systems and aren't part of NAIC SBS. They aren't accepted as jurisdiction codes, and the input schema says so.

"The maximum number of results, 25, were returned" warnings. Expected in targeted mode — it means that single query is genuinely larger than NAIC will return at once. Narrow the filter, or switch to enumerate, which subdivides and collects the full set.

Worried about missed records? Read gaps in the CHECKPOINT_naic-sbs key-value store record. If a prefix is listed there, those licencees couldn't be enumerated. An empty list means full coverage.

Frequent 403s or timeouts. Lower concurrency to 4, make sure useProxy is on, and consider a different proxyCountry.

Run stopped early. Check maxRequests. In enumerate mode, subdivision consumes requests quickly, so this ceiling can be reached before maxResults.


Data source and attribution

Data comes from the public NAIC State Based Systems external lookup API at api.prod.naic.org. This Actor is an independent tool and is not affiliated with or endorsed by the NAIC. State licence records are public regulatory filings — you are responsible for your own compliance with applicable data-protection and fair-practice obligations.

Changelog

See ./CHANGELOG.md.