FINRA BrokerCheck Scraper - Broker & Advisor Data
FINRA BrokerCheck Scraper
Scrape registered broker and investment adviser records from FINRA BrokerCheck via FINRA's public JSON API. Returns CRD numbers, employment history, license exams, state registrations, regulatory disclosures, and firm affiliations for 600,000+ registered financial professionals and 3,500+ firms.
FINRA BrokerCheck Scraper Features
- Searches both individual brokers/advisers and firms in a single actor
- Four operating modes: individual search, firm search, individual lookup by CRD, firm lookup by CRD
- Extracts 30+ fields per record — name, CRD, scope, employment history, exams, state registrations, disclosures
- Returns full employment history with dates, firm CRDs, and branch locations
- Includes regulatory disclosures: event date, type, resolution, initiator, allegations, and sanctions
- Filters by US state for individual searches, optional client-side firm-name filter
- Pure JSON API — no browser rendering, no proxy, no CAPTCHA solving
- Includes or excludes inactive records via a single flag
Who Uses FINRA BrokerCheck Data?
- Financial services sales teams — Build targeted lists of advisers by firm, state, or license type and feed them into your CRM
- Compliance and due diligence — Pull a broker's full employment history and disclosure record for KYC, hiring, or regulatory screening
- Wealth management recruiters — Identify advisers with specific licenses, tenure, or firm affiliations you want to poach
- Journalists and researchers — Track sanctions, customer complaints, and regulatory actions across the industry
- Fintech and RIA tech builders — Seed your product's adviser database with authoritative, government-sourced data
How FINRA BrokerCheck Scraper Works
- Pick a mode — search by name, search a firm, or look up specific CRD numbers
- The scraper hits FINRA's BrokerCheck API, paginates through listing results, and fetches the full detail record for each hit
- Each record is normalized into a flat, structured JSON object with consistent field names and formatted dates
- Results stream into the Apify dataset — you export CSV, JSON, or Excel from the console
Input
{
"mode": "individual_search",
"query": "Smith",
"state": "WY",
"includeInactive": false,
"includeDisclosures": true,
"maxItems": 100
}
| Field | Type | Default | Description |
|---|---|---|---|
mode |
string | individual_search |
One of individual_search, firm_search, by_crd_individual, by_crd_firm, crawl_all |
query |
string | Smith |
Name or keyword. Required for the two search modes (ignored by crawl_all) |
queries |
array | [] |
Search several names at once — each runs as its own search, results merged + de-duplicated by CRD. Takes priority over query |
state |
string | "" |
Two-letter state code (e.g. CA, NY, TX). Filters individual_search; for crawl_all, restricts the crawl to one state |
firmName |
string | "" |
Client-side substring filter on current-employer firm name (individuals) |
fetchDetails |
boolean | true |
true = full detail records (exams, disclosures, history). false = fast listing-level records (identity, current employer + location). Same price |
crdNumbers |
array | [] |
List of CRD numbers. Required for by_crd_individual and by_crd_firm |
includeInactive |
boolean | false |
Include records with InActive or NotInScope status |
includeDisclosures |
boolean | true |
Include full disclosure events in the output |
maxItems |
integer | 100 |
Maximum records to return. Set high (e.g. 1000000) for crawl_all |
Crawl the whole registry
FINRA's search API caps any single query at 9,000 results, so you can't pull the entire registry with one blank search. crawl_all works around this by automatically sharding the registry by state and name-prefix and de-duplicating by CRD:
{
"mode": "crawl_all",
"fetchDetails": false,
"maxItems": 1000000
}
- Leave
stateempty to crawl every state, or set it (e.g."CA") to crawl one state per run — handy for checkpointing large pulls and for keeping each run within the timeout. fetchDetails: falseemits fast listing-level records; this is the practical way to pull the whole registry (a listing-tier full crawl finishes in a few hours). Leave ittruefor full profiles, where a per-state run is recommended.- Memory: a full-registry crawl tracks every CRD seen for de-duplication — run
crawl_allwith 512 MB or more.
The crawler self-paces at a safe request rate — FINRA throttles aggressive clients hard — fetching detail profiles in parallel up to that ceiling. Full detail crawls of large states are still lengthy; pull them one state at a time, or use the listing tier for breadth.
Search multiple names at once
{
"mode": "individual_search",
"queries": ["Smith", "Jones", "Garcia"],
"state": "TX"
}
Firm search example
{
"mode": "firm_search",
"query": "Fidelity",
"maxItems": 50
}
Direct CRD lookup
{
"mode": "by_crd_individual",
"crdNumbers": ["1113790", "1056376"],
"includeInactive": true
}
FINRA BrokerCheck Scraper Output Fields
One schema covers both individuals and firms — the record_type field tells you which is which, and firm-only or individual-only fields are empty when not applicable.
Individual record
{
"record_type": "individual",
"crd_number": "1113790",
"full_name": "JOSEPH THOMAS SMITH",
"first_name": "JOSEPH",
"last_name": "SMITH",
"middle_name": "THOMAS",
"other_names": ["JOE SMITH", "SMITTY SMITH"],
"bc_scope": "Active",
"ia_scope": "Active",
"has_disclosures": false,
"disclosure_count": 0,
"industry_start_date": "1984-01-14",
"registration_count": 1,
"state_registration_count": 10,
"current_employer_name": "LPL FINANCIAL LLC",
"current_employer_crd": "6413",
"current_employer_city": "MADISON",
"current_employer_state": "NJ",
"employment_history": [
"LPL FINANCIAL LLC (CRD 6413) — MADISON, NJ [2020-05-07 — present]",
"SAGEPOINT FINANCIAL, INC. (CRD 133763) — MADISON, NJ [2007-11-20 — 2020-05-11]"
],
"license_exams": [
"Series 65 — Uniform Investment Adviser Law Examination (2002-08-02) [IA]",
"Series 7 — General Securities Representative Examination (1983-04-16) [BC]"
],
"state_registrations": [
"California — BC APPROVED 2020-05-07",
"New Jersey — IA APPROVED 2020-05-08"
],
"registered_sros": [
"FINRA APPROVED (Categories: Full Registration/General Securities Representative, Securities Trader)"
],
"disclosures": [],
"brokercheck_url": "https://brokercheck.finra.org/individual/summary/1113790"
}
| Field | Type | Description |
|---|---|---|
record_type |
string | Always individual or firm |
crd_number |
string | Central Registration Depository number |
full_name |
string | Full name (individuals only) |
first_name / last_name / middle_name |
string | Name parts |
other_names |
string[] | Alternate names, maiden names, nicknames |
bc_scope |
string | Broker-dealer registration scope: Active, InActive, NotInScope, Expanded |
ia_scope |
string | Investment adviser registration scope |
has_disclosures |
boolean | True if the record has disclosure events |
disclosure_count |
number | Number of disclosure events |
industry_start_date |
string | Date entered the securities industry (YYYY-MM-DD) |
registration_count |
number | Number of active FINRA registrations |
state_registration_count |
number | Number of active state registrations |
current_employer_name |
string | Current firm name |
current_employer_crd |
string | Current firm CRD |
current_employer_city / current_employer_state |
string | Current branch office location |
employment_history |
string[] | Formatted: "Firm Name (CRD) — City, ST [start — end]" |
license_exams |
string[] | Formatted: "Series 7 — Exam Name (YYYY-MM-DD) [scope]" |
state_registrations |
string[] | Formatted: "State — SCOPE STATUS YYYY-MM-DD" |
registered_sros |
string[] | Formatted SRO entries with status and registration categories |
disclosures |
string[] | Formatted disclosure events with date, type, initiator, allegations, sanctions |
brokercheck_url |
string | Direct URL to the BrokerCheck profile page |
Firm record
{
"record_type": "firm",
"crd_number": "166782",
"firm_name": "FIDELITY SELECTCO, LLC",
"firm_other_names": ["FIDELITY SELECTCO, LLC"],
"firm_sec_number": "801-77635",
"firm_ia_scope": "INACTIVE",
"firm_bc_scope": "",
"firm_has_disclosures": true,
"firm_branch_count": 0,
"firm_main_office_street": "6501 S FIDDLER'S GREEN CIRCLE, STE 300 - 600, SUITE 600",
"firm_main_office_city": "GREENWOOD VILLAGE",
"firm_main_office_state": "CO",
"firm_main_office_zip": "80111",
"firm_main_office_country": "United States",
"disclosures": [],
"brokercheck_url": "https://brokercheck.finra.org/firm/summary/166782"
}
| Field | Type | Description |
|---|---|---|
firm_name |
string | Firm legal name |
firm_other_names |
string[] | Alternate firm names |
firm_sec_number |
string | SEC file number (e.g. 801-12345 IA, 8-12345 BD) |
firm_ia_scope / firm_bc_scope |
string | Firm's IA and BD registration scopes |
firm_has_disclosures |
boolean | True if the firm has disclosure events |
firm_branch_count |
number | Number of firm branches |
firm_main_office_* |
string | Main office street, city, state, zip, country |
FAQ
How do I scrape FINRA BrokerCheck?
FINRA BrokerCheck Scraper pulls data from FINRA's public Elasticsearch-backed JSON API at api.brokercheck.finra.org. Pick a mode, set a query, and run it. No authentication, no CAPTCHA, no proxy setup — FINRA publishes this data on purpose.
How much does FINRA BrokerCheck Scraper cost to run?
FINRA BrokerCheck Scraper uses pay-per-event pricing: $0.10 per run start plus $0.001 per record. A 1,000-record run costs about $1.10, whether you pull full detail records or fast listing-level records (fetchDetails: false) — same price either way.
What data can I get from FINRA BrokerCheck?
FINRA BrokerCheck Scraper returns the full public record for each individual or firm — identity, CRD, scope, employment history, licenses and exams, state registrations, SRO memberships, and any regulatory disclosures (complaints, sanctions, bankruptcies). Roughly 30+ fields per record.
Can I filter by state or firm?
FINRA BrokerCheck Scraper supports a server-side state filter for individual searches (state: "CA") and a client-side substring match on current-employer firm name (firmName: "Goldman"). Full detail records include each person's license exams, so you can filter by exam (e.g. Series 79) in your own post-processing. For firm-level filtering, use firm_search mode with the firm name as the query.
Can I scrape every record in the registry?
Yes — use crawl_all mode. FINRA's search API caps any single query at 9,000 results, so a blank "get everything" search can't work. crawl_all automatically shards the registry by state and name-prefix and de-duplicates by CRD to walk past that cap. Set maxItems high, use fetchDetails: false for a fast listing-level pull, and run with 512 MB or more. Coverage is near-complete; FINRA exposes no bulk-export endpoint, so a guaranteed 100% dump isn't possible.
Does FINRA BrokerCheck Scraper need proxies?
FINRA BrokerCheck Scraper doesn't need proxies. It hits FINRA's public API at a conservative ~5 requests per second, which sits well under any silent throttle and has never tripped a rate limit in testing.
How do I look up specific brokers by CRD number?
Use mode: "by_crd_individual" with a crdNumbers array. Each CRD is fetched directly without going through search pagination, which is both faster and cheaper when you already know who you want.
Need More Features?
Need custom fields, bulk state sweeps, or a different regulatory data source? File an issue or get in touch.
Why Use FINRA BrokerCheck Scraper?
- Authoritative source — Data comes straight from FINRA's public API, not a screen-scraped copy
- Clean structured output — All array fields return primitive strings with consistent formatting, so you can load it into a database or spreadsheet without a cleanup pass
- Four modes, one actor — Search individuals, search firms, or look up CRDs directly without needing separate tools for each workflow