CFP Board Scraper — Certified Financial Planner Leads
Pricing
$4.00 / 1,000 per cfp® professional returneds
CFP Board Scraper — Certified Financial Planner Leads
Export CFP Board's Find a CFP Professional directory: planner name, firm, office addresses, phone, website, LinkedIn, year certified, planning services, client specialties, languages, CRD with BrokerCheck/IAPD links, plus optional discipline and bankruptcy flags. Filter by state, city, ZIP or firm.
Pricing
$4.00 / 1,000 per cfp® professional returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 days ago
Last modified
Categories
Share
Export CFP Board's public Find a CFP® Professional directory as a clean lead list. One row = one CERTIFIED FINANCIAL PLANNER™ professional, carrying fullName, firmName, phone, website, linkedinUrl, addressLine1, city, state, postalCode, latitude, longitude, certificationYear, yearsCertified, planningServices, specialties, languages, designations, minInvestableAssets and the crd number that links straight to FINRA BrokerCheck and SEC IAPD.
72,207 certified professionals live on 2026-08-12 — the whole directory, enumerable to the last row, not a top-N sample. Filter by state, city, ZIP, firm, planning service, client specialty, language, minimum-asset band or a lat/long radius — or look up one person by name.
$0.004 per planner — $4 per 1,000. No login. No API key. No cookies. No CAPTCHA solving.
{ "states": ["CA"], "maxItems": 100 }
Click Try for free and hit Start — that is the input this Actor ships with. It returned 100 California planners in 5 seconds on 2026-08-12, for $0.40.
Quick start — data in about a minute
- Click Try for free on this page (an Apify account is free; no card for the free tier).
- Leave every field alone, or pick your states from the States drop-down — each one shows its live planner count, so you can size the run before you spend.
- Press Start.
- Open the Dataset tab when the run turns green.
- Export CSV / Excel / JSON — or hit the API URL on the same tab.
No coding required. Every filter on the form is a drop-down read from CFP Board's own live vocabulary, so there is nothing to spell correctly.
From the API
# pip install apify-clientfrom apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("scrapersdelight/cfp-board-planner-scraper").call(run_input={"states": ["CA", "NY"],"planningServices": ["Tax Planning"],"requirePhone": True,"maxItems": 500,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["fullName"], row["firmName"], row["phone"], row["crd"])
// npm i apify-clientimport { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('scrapersdelight/cfp-board-planner-scraper').call({states: ['MA'],cities: ['Boston, MA'],maxItems: 200,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0]);
# One-person verification, synchronous — returns the row in the response bodycurl -X POST "https://api.apify.com/v2/acts/scrapersdelight~cfp-board-planner-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H 'Content-Type: application/json' \-d '{"firstName":"John","lastName":"Miller","states":["CA"],"maxItems":5}'
The wedge: the CRD number, on 97.6% of rows
A name-and-phone list of financial advisors is a commodity. What makes this row worth buying is that 97.6% of planners carry a crd — the FINRA Central Registration Depository number — and the Actor emits the two URLs that number resolves to:
crd "6872220"finraBrokerCheckUrl "https://brokercheck.finra.org/individual/summary/6872220"secAdviserInfoUrl "https://adviserinfo.sec.gov/individual/summary/6872220"
That is a join key into the regulated world. With it you can attach employment history, exam record, state registrations, firm affiliation and disciplinary history from BrokerCheck and IAPD to 97.6% of a 72,207-person list, without ever running a name match. Google Maps cannot give you that. A generic "financial advisor" scrape cannot give you that. It is the difference between a mailing list and a dataset you can model on.
Two more things this export carries that the CFP Board profile page never shows in one place:
offices[]— every office, not just the headquarters. 10.4% of planners list more than one office (measured on 2,500 contiguous rows), sometimes in different states. You get the full array with a per-office street address, city, state, ZIP, latitude and longitude, plusofficeStates[]andofficeCount. If you are assigning territory, the second office is the one that decides it.designations[]— the letters after the CFP. CFA, CPA, ChFC, CLU, AIF, CIMA, PFS, Licensed Attorney, resolved from CFP Board's GUIDs into readable labels (13.0% of rows carry at least one). A CFP® who is also a CPA is a different sales conversation than a CFP® who is not.
Read this before you buy rows
- There are no email addresses here, and there is no
emailcolumn. CFP Board publishes none — the field exists in the source payload and came back empty on 0 of 2,500 rows (re-measured 2026-08-12, and 0.0% across an earlier 6,000-row sweep). See Honest limits for what to do instead. firmUrlis effectively empty — 0.2%, five rows in 2,500. It is kept in the schema because CFP Board populates it occasionally, but do not plan against it. The field you want iswebsite(82.2%).- A city or ZIP filter with no state walks the whole directory. CFP Board's
cityExactparameter is a relevance boost, not a filter, so this Actor filters city and ZIP on the rows themselves. Write cities as"Boston, MA"and the state narrows the server-side search for you — that is the difference between ~25 requests and ~723. specialtiesis the most aggressive filter on the form (47.4% fill). Fewer than half of all planners declare a client segment at all. Use it to find a practice, not to size a market — a "Veterans" filter returning 2,236 planners is a floor, not a census.- The top investable-asset band filters nothing. The bands are cumulative and every planner states a minimum, so "Accepts $5,000,000 or less" returns all 72,207. Pick a low band to find planners who take smaller clients.
What you get
One row per certified professional. All timestamps are ISO-8601 UTC; latitude/longitude are decimal degrees; minInvestableAssets is a whole number of US dollars.
Identity
| Field | Type | Notes |
|---|---|---|
cfpId | string | CFP Board's profile GUID — the dedupe key |
profileUrl | string | Canonical public profile page |
fullName | string | First + middle + last, marks stripped |
fullNameDisplay | string | As CFP Board renders it, e.g. Mr. John T Miller |
prefix / firstName / middleName / lastName / suffix | string | Split name parts |
memberNumber | string | CFP Board internal record number |
photoUrl | string | Headshot URL |
Credential
| Field | Type | Notes |
|---|---|---|
certificationStatus | string | Certified on every row — see limit 4 |
certificationYear | integer | Year the CFP® marks were awarded |
yearsCertified | integer | Current year minus certificationYear |
cfpMarks | string | The marks string as published |
designations[] | array | CFA, CPA, ChFC, CLU, AIF, CIMA, PFS, Licensed Attorney |
designationIds[] | array | CFP Board's raw GUIDs, for any label we cannot resolve |
Firm & contact
| Field | Type | Notes |
|---|---|---|
firmName | string | 99.6% fill |
phone | string | Primary, formatted (631) 592-2028 x1; extensions preserved |
phones[] | array | Every published number |
website | string | 82.2% — the handle you enrich from |
linkedinUrl | string | 42.3% |
firmUrl | string | 0.2% — effectively empty, see limit 2 |
Location
| Field | Type | Notes |
|---|---|---|
addressLine1 / addressLine2 / city / state / postalCode | string | Primary office |
latitude / longitude | number | Primary office, decimal degrees |
offices[] | array | Every office, each with its own address + geo |
officeCount | integer | 10.4% of planners have more than 1 |
officeStates[] | array | Every state this planner has an office in |
Practice
| Field | Type | Notes |
|---|---|---|
planningServices[] | array | 21 possible values, 91.2% fill |
specialties[] | array | 10 client segments, 47.4% fill |
languages[] | array | 25 possible values, 94.6% fill |
minInvestableAssets | integer | 100% fill — every planner states one |
paymentOptionIds[] / paymentOptionCount | array / integer | Opaque GUIDs — see limit 2 in Honest limits |
Regulatory
| Field | Type | Notes |
|---|---|---|
crd | string | 97.6% — the FINRA join key |
finraBrokerCheckUrl / secAdviserInfoUrl | string | Resolved from crd |
hasDiscipline / hasBankruptcy | boolean | null unless includeDisclosures is on |
disclosureUrl | string | CFP Board background page for this planner |
disclosuresChecked | boolean | Tells you whether the two flags above are meaningful |
Provenance
| Field | Type | Notes |
|---|---|---|
sourceUrl | string | Where the row came from |
scrapedAt | string | ISO-8601 UTC |
Field fill — measured on 2,500 contiguous rows
Sample: one run of this Actor with no filters, walking contiguous pages 1–25 through the Apify datacenter proxy on 2026-08-12 — 2,500 rows, 2,500 unique. Sorted by fill, so the sparse fields are impossible to miss.
| Field | Fill |
|---|---|
cfpId, profileUrl, sourceUrl, scrapedAt | 100% |
fullName, fullNameDisplay, firstName, lastName | 100% |
addressLine1, city, state, postalCode | 100% |
certificationStatus, cfpMarks, certificationYear, yearsCertified | 100% |
offices[], officeCount, officeStates[] | 100% |
minInvestableAssets, paymentOptionCount | 100% |
photoUrl, memberNumber | 100% |
latitude, longitude | 99.8% |
firmName | 99.6% |
crd + finraBrokerCheckUrl + secAdviserInfoUrl | 97.6% |
languages[] | 94.6% |
planningServices[] | 91.2% |
prefix | 86.3% |
website | 82.2% |
phone, phones[] | 72.1% |
middleName | 69.0% |
specialties[] | 47.4% |
linkedinUrl | 42.3% |
paymentOptionIds[] | 25.4% |
designations[], designationIds[] | 13.0% |
suffix | 3.2% |
addressLine2 | 0.7% |
firmUrl | 0.2% |
email | 0.0% — no such column exists |
A separate 6,000-row sweep measured phone at 73.3% and website at 82.7% — the two samples bracket each other, which is what a stable fill rate looks like.
hasDiscipline, hasBankruptcy and disclosureUrl are 0% in this table because includeDisclosures was off. With it on they fill on 100% of rows (50/50 on a New York run, same date).
The headline that could mislead you: this is not an email product, and it is only a phone product 72.1% of the time. It is a credential and firmographic product with a regulatory join key on 97.6% of rows. Buy it for the CRD, the certification year and the practice fields; treat the phone as a bonus and set requirePhone if you need it guaranteed.
Every run prints its own scope totals in the log.
Sample row
A real row from the default run on 2026-08-12, unedited:
{"cfpId": "a1340a68-58d1-4410-bceb-30bf47b9696b","profileUrl": "https://www.letsmakeaplan.org/find-a-cfp-professional/certified-professional-profile/a1340a68-58d1-4410-bceb-30bf47b9696b","fullNameDisplay": "Mr. John T Miller","prefix": "Mr.","firstName": "John","middleName": "T","lastName": "Miller","suffix": null,"fullName": "John T Miller","cfpMarks": "CFP","certificationStatus": "Certified","certificationYear": 2022,"yearsCertified": 4,"firmName": "Empirical Wealth Management","website": "https://www.empirical.net/","firmUrl": null,"linkedinUrl": "https://www.linkedin.com/in/john-miller-cpa-cfp®-1773b0103","phone": "(206) 518-9163","phones": ["(206) 518-9163"],"addressLine1": "633 Menlo Ave Ste 100","addressLine2": null,"city": "Menlo Park","state": "CA","postalCode": "94025-4711","latitude": 37.547833,"longitude": -122.326471,"officeCount": 1,"offices": [{"addressLine1": "633 Menlo Ave Ste 100","addressLine2": null,"city": "Menlo Park","state": "CA","postalCode": "94025-4711","latitude": 37.547833,"longitude": -122.326471}],"officeStates": ["CA"],"planningServices": ["Socially Responsible Investing", "Divorce Planning", "Investment Planning","Inheritance", "Employee and Employer Plan Benefits", "Education Planning","Social Security Planning", "Insurance Planning","Comprehensive Financial Planning", "Tax Planning", "Estate Planning","Retirement Planning"],"specialties": ["Young Professionals", "Retirees"],"languages": ["English"],"designations": ["Certified Public Accountant"],"designationIds": ["e82676e9-7e47-4782-b36a-cc56c108e896"],"paymentOptionIds": ["8ecb3ee3-3f08-405c-bd1b-7781e254c79d"],"paymentOptionCount": 1,"minInvestableAssets": 1000000,"crd": "6872220","finraBrokerCheckUrl": "https://brokercheck.finra.org/individual/summary/6872220","secAdviserInfoUrl": "https://adviserinfo.sec.gov/individual/summary/6872220","hasDiscipline": null,"hasBankruptcy": null,"disclosureUrl": null,"disclosuresChecked": false,"photoUrl": "https://login.cfp.net/eweb/fileviewer.aspx?itemkey=00000000-0000-0000-0000-000000000000&objectName=profile_images&file=449043","memberNumber": "449043","sourceUrl": "https://www.letsmakeaplan.org/find-a-cfp-professional/certified-professional-profile/a1340a68-58d1-4410-bceb-30bf47b9696b","scrapedAt": "2026-08-13T02:02:10.320Z"}
A different planner, run with includeDisclosures: true — the four fields that change (real row, New York run, 2026-08-12):
{"fullName": "Henry P. Cerruti","firmName": "Northwestern Mutual","hasDiscipline": false,"hasBankruptcy": false,"disclosureUrl": "https://www.cfp.net/verify-a-cfp-professional/certification-and-background/131c2d4e-2ee5-49a9-b50d-d51d57d4771f","disclosuresChecked": true}
Fields people misread:
hasDiscipline: falsemeans checked and clean.hasDiscipline: nullmeans not checked —disclosuresCheckedis the field that tells them apart. Never treatnullas clean.minInvestableAssetsis the planner's stated minimum for a client, in dollars. It is not their AUM.1000000means "I take clients with $1M+", not "I manage $1M".yearsCertifiedis derived (current year −certificationYear), not published by CFP Board.phones[]keeps extensions ((631) 592-2028 x1).phoneis simplyphones[0].designationIds[]is always present whendesignations[]is; if CFP Board adds a credential we have no label for, the GUID still ships and the run logs a warning rather than dropping it.
How to run it
Recipe 1 — the default: a cheap first look
{ "states": ["CA"], "maxItems": 100 }
100 rows, 5 seconds, $0.40. This is what ships prefilled.
Recipe 2 — a whole state, end to end
{ "states": ["MA"], "maxItems": 0 }
maxItems: 0 means everything in scope. Massachusetts = 2,408 planners = $9.63.
Recipe 3 — one metro, cheaply
{ "states": ["MA"], "cities": ["Boston, MA"], "maxItems": 0 }
Writing the city as "Boston, MA" narrows the server-side walk to Massachusetts (2,408 rows, ~25 requests) instead of the full 72,207 (~723 requests). Rows outside Boston are dropped before billing.
Recipe 4 — a firm roster (competitor or acquisition target)
{ "firmName": "Edward Jones", "maxItems": 0 }
4,461 planners. Applied server-side, so you pay for rows, not for searching.
Recipe 5 — Spanish-speaking planners who take smaller clients
{"languages": ["Spanish"],"clientInvestableAssets": "100000","requirePhone": true,"maxItems": 0}
Spanish is 2,053 planners nationally; the asset band and phone requirement cut it further. All three filters are free — the language and asset filters run server-side, and requirePhone drops rows before they are billed.
Recipe 6 — everyone within 25 miles of downtown Chicago
{ "latitude": "41.8781", "longitude": "-87.6298", "radiusMiles": 25, "maxItems": 0 }
CFP Board's own distance filter. A planner is returned if any of their offices falls inside the circle.
Recipe 7 — verify one person
{ "firstName": "John", "lastName": "Miller", "states": ["CA"], "maxItems": 5 }
Does this individual actually hold the CFP® marks, since when, and what is their CRD? Usually a one-row, $0.004 answer. Pair with the run-sync-get-dataset-items cURL call above to get it back in the HTTP response.
Recipe 8 — a compliance / due-diligence pull
{ "states": ["NY"], "includeDisclosures": true, "maxItems": 0 }
Fills hasDiscipline and hasBankruptcy from CFP Board's own verification service. Measurably slower: 100 planners without disclosures took 5 seconds; 50 planners with disclosures took 81 seconds (measured 2026-08-12). The price per planner is identical either way.
Recipe 9 — the whole directory
{ "maxItems": 0 }
72,207 planners, ~723 requests, about $289. Schedule it monthly from the Schedules tab to track new certifications.
Input
Every field ships with a default or a prefill, so a zero-edit run works. Fields are listed in the order they appear on the form.
| Field | Type | Default | What it does |
|---|---|---|---|
states | multi-select | ["CA"] (prefill) | 54 states and territories, each labelled with its live planner count. Empty = the whole 72,207-row directory. Multi-state runs dedupe across scopes. |
cities | string list | [] | "Boston, MA" (recommended) or "Boston". With the state attached it also narrows the search server-side. Non-matching rows are dropped before billing. |
zipCodes | string list | [] | 5-digit ZIPs, matched against every office on a profile. Combine with states or the run walks all 723 pages. |
latitude | text | "" | Radius-search centre, e.g. 40.7128. Needs longitude too. |
longitude | text | "" | e.g. -74.0060. West is negative. |
radiusMiles | number | 25 | 1–500. Ignored unless both coordinates are set. |
planningServices | multi-select | [] | CFP Board's 21 live services, each with its national count. Multiple values = planner must offer all of them. Server-side. |
specialties | multi-select | [] | 10 client segments with counts. Only 47.4% of planners declare any — the harshest filter here. Server-side. |
languages | multi-select | [] | 25 languages with counts. English is 68,308 of 72,207, so it is not a filter. Server-side. |
clientInvestableAssets | select | "any" | Cumulative bands: planners who accept a client at or below the level you pick. Server-side. |
firmName | text | "" | Partial match, server-side. "Edward Jones" = 4,461 planners. |
firstName | text | "" | Use with lastName to verify one person. |
lastName | text | "" | See above. |
requirePhone | checkbox | false | Drop rows with no phone (~27% of any scope). Dropped rows are not billed. |
requireWebsite | checkbox | false | Drop rows with no website (~17%). Dropped rows are not billed. |
includeDisclosures | checkbox | false | Fill hasDiscipline / hasBankruptcy. Roughly 0.05 s/row becomes 1.6 s/row (measured). Same price. |
maxItems | number | 100 | Hard cap and cost ceiling. 0 = everything in scope. Duplicates never count against it. |
proxyConfiguration | proxy | Apify datacenter | See the transport ladder below. You should not need to change this. |
The drop-down vocabularies
Every enumerable filter is a drop-down populated from CFP Board's own live facet payload, read on 2026-08-12. You cannot mistype a filter, and each option carries its national count so you can size a run before you spend.
Planning services (21): Retirement Planning 55,593 · Comprehensive Financial Planning 54,331 · Investment Planning 54,254 · Insurance Planning 36,485 · Estate Planning 35,993 · Tax Planning 25,876 · Employee and Employer Plan Benefits 21,192 · Education Planning 18,432 · Retirement Income Management 18,254 · Business Succession Planning 11,425 · Long-term Care 8,704 · Social Security Planning 8,502 · Inheritance 8,260 · Small Business Planning 7,780 · Life Transitions 7,661 · Budgeting 6,959 · Divorce Planning 5,915 · Debt Management 4,825 · Socially Responsible Investing 3,755 · Elder Care 2,386 · Health Care 1,389
Client specialties (10): Retirees 16,883 · Young Professionals 11,858 · Intergenerational Families 10,278 · Women 8,688 · Widows/Widowers 8,279 · Government Employees and Military Servicepeople 3,272 · LGBTQ+ Individuals/Couples 2,752 · Veterans 2,236 · Special Needs Individuals 2,033 · Faith-Based Investing 710
Languages (25): English 68,308 · Spanish 2,053 · Mandarin 553 · French 462 · German 302 · Cantonese 238 · Portuguese 206 · Hindi 202 · Russian 201 · Italian 175 · Korean 147 · Japanese 97 · Arabic 95 · Gujarati 90 · Vietnamese 82 · Hebrew 81 · Greek 79 · Polish 71 · Armenian 62 · American Sign Language 52 · Tagalog 52 · Urdu 52 · Persian 51 · French Creole 15 · Thai 1
Client investable assets (cumulative): $0+ 36,041 · $100,000 or less 42,927 · $250,000 or less 52,131 · $500,000 or less 62,192 · $1,000,000 or less 70,568 · $5,000,000 or less 72,207
States and territories (54), with live counts measured 2026-08-12: CA 7,522 · FL 4,884 · TX 4,874 · NY 4,126 · PA 3,650 · IL 3,432 · OH 2,881 · NJ 2,654 · NC 2,578 · MA 2,408 · MI 2,306 · VA 2,139 · GA 2,102 · MN 2,094 · CO 2,013 · WA 1,779 · MD 1,727 · MO 1,535 · AZ 1,531 · WI 1,526 · TN 1,428 · IN 1,400 · CT 1,136 · SC 964 · OR 899 · KS 890 · IA 810 · KY 776 · UT 696 · AL 631 · LA 621 · NH 523 · NE 512 · OK 429 · NV 360 · ID 301 · AR 297 · DE 296 · RI 280 · HI 266 · ME 252 · MT 224 · DC 223 · MS 218 · SD 210 · NM 184 · ND 151 · VT 141 · WV 133 · WY 90 · AK 89 · PR 28 · GU 3 · VI 3
American Samoa and the Northern Mariana Islands are deliberately absent — CFP Board lists 0 professionals in each, and offering a scope that can only return zero would be a trap.
Pricing
$0.004 per CFP® professional returned — $4 per 1,000. Charged on the planner-scraped event. There is no monthly platform fee from this Actor and no charge for starting a run.
Every $1 you spend is 250 planners.
| Run | Planners | Cost |
|---|---|---|
| The default first click | 100 | $0.40 |
| Boston, MA | 477 | $1.91 |
| Massachusetts, end to end | 2,408 | $9.63 |
| New York State, end to end | 4,126 | $16.50 |
| California, end to end | 7,522 | $30.09 |
| Every Edward Jones planner | 4,461 | $17.84 |
| Every Spanish-speaking planner in the US | 2,053 | $8.21 |
| The entire directory | 72,207 | $288.83 |
What you are never charged for:
- Rows removed by your filters.
requirePhone,requireWebsite,citiesandzipCodesall drop rows before billing — a narrow filter costs you run time and this Actor its proxy budget, not your money. - The same planner twice. Duplicates are dropped on the profile GUID before anything is pushed, so a multi-state run never bills you for the planner with offices in two of them.
- Retries, proxy traffic, or the facet-priming request that validates your filters before the walk starts.
includeDisclosures. It multiplies run time (5 s for 100 planners without, 81 s for 50 with — measured 2026-08-12) and costs exactly the same per row.
Atomicity: rows are charged as they are pushed (Actor.pushData(items, 'planner-scraped')), never delivered-then-billed. If you hit a platform spend cap mid-run you get whole rows and a stop, not a half-billed dataset.
maxItems is your hard cost cap — default 100, set 0 for everything in scope.
Honest limits
1. No email addresses. None. There is no email column and nothing here can produce one. CFP Board publishes no email for any professional — the field exists in their payload and was empty on 0 of 2,500 rows re-measured 2026-08-12, and 0.0% across an earlier 6,000-row sweep. Any CFP-directory product advertising emails is joining a different source to this one. What to do instead: take the website column (82.2%) and run it through Decision-Maker Email Finder or Local Business Contact Enricher; or if you need advisors who publish an email directly, use the NAPFA Advisor Scraper sibling instead.
2. Compensation method is stored but suppressed, so you get IDs, not labels. CFP Board holds each planner's payment options and returns them as opaque GUIDs (5 distinct values, on 25.4% of rows), while the site ships DisplayPaymentOptions: false — the "Payment Options" panel on every live profile renders explanatory boilerplate and no labels. There is no public byte anywhere on cfp.net or letsmakeaplan.org that names them. You get paymentOptionIds[] and paymentOptionCount, which are stable and let you group planners by payment model; this Actor will not invent "fee-only" / "commission" labels CFP Board does not publish. If CFP Board switches the labels back on, this Actor will resolve them.
3. firmUrl is 0.2% — five rows in 2,500. A site-side data-completeness gap, not a scraping bug: the field is simply blank on almost every profile. Use website (82.2%) instead. It stays in the schema because those five rows are real.
4. Discipline and bankruptcy flags are opt-in and slow. includeDisclosures cross-references CFP Board's own verification service, which is keyed by name rather than by id, so it costs roughly one extra request per distinct name — measured at 81 seconds for 50 planners against 5 seconds for 100 without. About 1.0% of professionals carry a flag (measured on 1,000 verification rows). Leave it off and both fields are null; disclosuresChecked tells you which. disclosureUrl on every checked row links to that planner's full CFP Board background page, which additionally shows their FINRA and SEC disciplinary status.
5. certificationStatus is "Certified" on every row. The directory only lists currently-certified professionals; revoked and lapsed CFP® professionals are not in it, so you cannot use this Actor to find someone who lost their marks. The field is kept so that a future status change is visible rather than silent. For lapsed or disciplined individuals, follow disclosureUrl or the crd into BrokerCheck.
6. City and ZIP are filtered on our side, on purpose. CFP Board's cityExact and postalCodeExact parameters are relevance boosts, not filters — asking for Boston returns all 72,207 rows with Boston sorted first. This Actor ignores them and matches your cities and ZIPs against each planner's actual office addresses, so a city run returns only that city. The trade-off is that a city or ZIP filter with no state has to walk the whole directory. Write cities as "Boston, MA".
7. The directory drifts day to day. It read 72,207 on 2026-08-12 — 722 full pages of 100 plus 7 rows on page 723, with page 724 empty. An earlier full enumeration measured 72,210. Certifications are issued and lapse continuously. Treat any total on this page as a measurement with a date on it, not a constant.
8. US only. CFP Board's Find a CFP® Professional directory covers the United States and its territories. There is no international scope to request.
9. No login, no API key, no CAPTCHA solving. This Actor reads a public JSON search endpoint. It does not authenticate, does not touch the contact-a-planner form behind Cloudflare Turnstile, and does not attempt any challenge. If CFP Board ever puts the search behind auth, this Actor will fail loudly rather than work around it.
How it works, and the transport ladder
CFP Board's directory is a plain JSON search API — no key, no cookie, no login, no token:
GET https://www.letsmakeaplan.org/api/feature/lmapprofilesearch/search?limit=100&pg=<n>&sort=random&randomKey=1[&stateExact=CA][&company=…][&facet GUIDs…]
The Cloudflare Turnstile widget on the page guards the contact-this-planner form, not the search. Filter vocabularies are read from the live facet payload on the first response of every run, so a renamed or newly added service keeps working — and an unrecognised label stops the run with CFP Board's current list printed, instead of silently returning nothing. Disclosures, when enabled, come from CFP Board's own verification host (cfp.net) keyed by the same GUID.
Transport, measured through the Apify proxy rather than assumed:
| Rung | Result |
|---|---|
| Direct, no proxy (residential home line) | 5/5 search + 5/5 verify — reported, then ignored: no Apify container has a residential IP |
| Apify datacenter proxy (default) | 25/25 (100%) on sustained contiguous deep pages · clean 60-page sweep · clean 76-page California walk · 20/20 (100%) on the verification host |
| Apify RESIDENTIAL proxy | 5/5 search + 5/5 verify — no better, and it costs more |
Datacenter is the default because it is the rung that cleared sustained load, and because a 723-page walk from one fixed egress IP is exactly what a Cloudflare rate rule exists to catch — a rotating pool is safer than a single address.
The proxy itself throws the occasional 595/ECONNRESET, so every request retries on a fresh IP (5 attempts, backing off). That is not theoretical: the 25-page, 2,500-row verification run on 2026-08-12 hit exactly one 595 on page 12, the retry cleared it on a new IP, and the run finished with all 2,500 rows in 127 seconds. CFP Board itself never returned a non-200 in any of it.
Two API traps this Actor works around, both of which silently corrupt a naive scraper:
limitcaps at 100. Ask for 200 and the API returns 10 rows while still reportingtotalPagesas though it had honoured 200 — you would walk 362 pages, collect 5% of the data, and believe you had all of it. The page size is hard-clamped to 100 and the row count is asserted on every page.cityExactandpostalCodeExactare relevance boosts, not filters. Passing them through is the classic "my city scrape returned the whole country" bug. This Actor sends onlystateExact— which is a real filter, and is case-sensitive:stateExact=nyreturns 0,stateExact=NYreturns 4,126.
Uniqueness and deduplication
Measured on contiguous page walks, because sparse-offset sampling proves nothing:
| Walk | Rows | Unique | Duplicates |
|---|---|---|---|
| Unfiltered, pages 1–25 (re-measured 2026-08-12) | 2,500 | 2,500 | 0 (0.00%) |
| California, pages 1–76, end to end | 7,522 | 7,522 | 0 — an exact match to CFP Board's own reported total |
| Deep contiguous pages 200–239 | 4,000 | 4,000 | 0 |
sort=random is seeded by a randomKey that this Actor pins to 1 for the whole run: the same key returns a byte-identical permutation on repeat calls, while a different key gives 0/100 overlap on page 1. Without pinning, a paged walk would reshuffle underneath itself and duplicate heavily.
The dedupe key is cfpId, CFP Board's canonical profile GUID — the same one the profile URL is built from. Deduplication happens before anything is pushed, so the dataset and your bill never hold the same person twice.
Where duplicates would otherwise come from: planners with offices in more than one state (10.4% have multiple offices). Summing all 56 state and territory scopes gives 73,225 rows against a directory of 72,207 — so at least 1,018 rows are the same professional surfacing in a second state. Those are collapsed to one billed row.
Across runs: deduplication is per-run. Two separate runs over overlapping scopes will return the same people. Use distinct state scopes, or diff on cfpId after export.
When a run stops early
This Actor never ends a run in a red Failed state, and never finishes silently green on an empty dataset. Whatever stops it, the run ends Succeeded and the reason is written into the run's status message (visible at the top of the run, no log-reading required), so an automation reading run status is not tripped by a transient CFP Board hiccup or by an over-narrow filter.
-
Zero rows says why, with the scope, the page count, the number of rows your filters dropped, and the filters themselves:
0 CFP® professionals returned after fetching 1 page(s) and dropping 90 row(s) on your filters. Filters in play: states=WY, cities=Atlantis, WY. Check the state codes (2-letter, e.g. "CA") and that city names match CFP Board's spelling, or clear the filters and re-run. Nothing was charged. -
An unrecognised filter label stops the run before anything is fetched or billed, and prints CFP Board's live vocabulary:
"Crypto Planning" is not a valid planning service. CFP Board's list is: Retirement Planning, Comprehensive Financial Planning, Investment Planning, … Health Care.The drop-downs make this unreachable from the Console; it protects API callers.
-
A changed page-size contract stops the walk. If the API ever returns more rows than the clamped page size, the run stops and says so rather than shipping a corrupted walk. Rows already collected are still delivered.
-
A shortfall warns loudly. If a page returns fewer rows than promised while more were expected, the log says so with both numbers, so a mid-run index shift is visible rather than silent.
-
An unresolvable designation GUID warns and still ships, in
designationIds[], rather than being dropped. -
A changed endpoint shape stops the run with the URL, telling you the Actor needs an update rather than returning junk. Nothing is charged.
-
The run's time limit is honoured, not hit. The Actor reads the platform's own kill time and stops fetching new pages with room to spare, flushes everything already collected, and reports "stopped early at the run time limit". It does not get killed mid-flight, so you never lose collected rows to a timeout. Measured: unbounded runs under a 120-second limit finish in 62–67 seconds, Succeeded, with data — three for three.
-
Your spend cap is honoured exactly. Rows are billed and delivered in the same call, so a run that reaches its max-total-charge stops cleanly on a whole row. Measured at a $0.10 cap: 25 rows delivered, 25 rows billed, $0.10 exactly — never a delivered row that was not billed, never a billed row that was not delivered.
If a run returns zero rows, the status message tells you which filter did it.
Who buys this
- Wealthtech and advisor-software vendors — Orion, Envestnet, eMoney, RightCapital, Holistiplan, Altruist and their competitors.
planningServices[]tells you who sells tax planning (25,876) or estate planning (35,993);firmNametells you whether they are already inside a wirehouse's tech stack. - Custodians and RIA platforms —
firmNameplusofficeStates[]finds independent practices by territory;crdjoins to IAPD to check whether the firm is already registered somewhere you compete. - Advisor recruiters and RIA M&A aggregators —
certificationYearandyearsCertifiedare the tenure signal;firmNameplusofficeCountfinds multi-office practices worth a conversation. A firm roster is onefirmNamerun away. - Compliance, KYC and background-check vendors — the 97.6%
crdfill plusincludeDisclosures(1.0% flagged) is a primary-source-adjacent credential check keyed to FINRA and SEC identifiers. - Insurance and annuity wholesalers — 36,485 planners list Insurance Planning and 8,704 list Long-term Care;
minInvestableAssetsseparates the mass-affluent practices from the HNW ones. - Financial-media and lead-gen marketplaces —
languages[]andspecialties[]build the matching taxonomy (2,053 Spanish speakers, 2,236 serving Veterans, 8,688 serving Women) that a consumer-facing "find an advisor" product needs.
Sibling Actors — which one do you actually want
| Actor | Universe | Record | Size | Carries email? |
|---|---|---|---|---|
| CFP Board Scraper (this one) | Everyone who holds the CFP® certification, at any firm | Certified individual | 72,207 | No — CFP Board publishes none |
| NAPFA Advisor Scraper | Members of NAPFA, the fee-only association | Individual + their firm | ~4,000 | Yes, ~65% direct + 100% firm fallback |
| SEC Investment Adviser Scraper | Investment adviser firms registered with the SEC or a state | Firm (Form ADV) | ~45,500 | Firm-level only |
| Decision-Maker Email Finder | Any company domain | Person + email | — | That is the whole job |
| Local Business Contact Enricher | Any business website | Name, role, email | — | That is the whole job |
Put plainly: NAPFA is a small, pre-qualified fee-only membership; SEC IAPD is the regulated firm register with AUM and Form ADV disciplinary items; this one is the individual credential holder — by far the largest of the three, and the only one that tells you who, personally, holds the CFP marks, since when, and what they specialise in. Many CFP® professionals here work at wirehouses and insurers that never appear in NAPFA and are not themselves an SEC-registered firm.
Go to CFP Board for the credential and the CRD. Go to NAPFA for a direct email. Go to SEC IAPD for AUM.
Compared with the alternatives
| This Actor | Clicking through the directory | Your own scraper | Buying an advisor list | |
|---|---|---|---|---|
| Setup | Minutes | — | Days | Sales call |
| Whole directory | 72,207 rows, ~$289 | ~72,000 page views | Yours to build | Often $2,000+ |
| CRD + BrokerCheck/IAPD links | 97.6% | Manual | If you build it | Sometimes |
| Every office, not just HQ | Yes (offices[]) | Manual | If you build it | Rarely |
The limit=200 trap | Handled | n/a | Silently loses 95% of your data | n/a |
The cityExact trap | Handled | n/a | Returns the whole country | n/a |
| Freshness | Live, this run | Live | Live | Whenever they last refreshed |
| Maintenance | Ours | — | Yours | Theirs |
FAQ
Does this need an account, a login or an API key? No. CFP Board's search endpoint is public JSON. The Actor does not authenticate and collects nothing behind any login.
How many CFP professionals can I actually get? All of them: 72,207 on 2026-08-12. This is a full enumeration, not a capped sample — the walk runs to page 723, which returned the final 7 rows on that date (page 724 is empty), an exact match to CFP Board's own reported total.
Can I get email addresses?
No, and no CFP Board export can — CFP Board publishes none, measured 0 of 2,500 rows. Use the 82.2% website column with an email-finder Actor, or use the NAPFA sibling.
Does it need a proxy? It uses the Apify datacenter pool by default, which measured 100% on sustained contiguous paging. You do not need to configure anything, and residential measured no better.
Do I get charged for rows my filters remove?
No. requirePhone, requireWebsite, cities and zipCodes all drop rows before billing. You are billed per planner delivered.
Two runs — will I get duplicates?
Within a run, no: 0.00% duplicates measured on 2,500, 7,522 and 4,000-row contiguous walks, deduped on cfpId before billing. Across runs, yes — dedupe is per-run. Use distinct state scopes or diff on cfpId.
Will a run ever succeed with zero rows? Only when your filters genuinely match nobody — and when that happens the run's status message names the scope, the page count and the filters in play, and nothing is charged. The Actor does not end runs in a red Failed state, because an over-narrow filter or a transient CFP Board hiccup is not a broken Actor and should not break your automation. There is no such thing as a silent empty run.
How much does the whole directory cost? 72,207 planners × $0.004 = $288.83. California alone is $30.09; New York is $16.50.
How do I find planners in one city without paying for the whole country?
Write the city as "Boston, MA". The state narrows the server-side search to 2,408 rows instead of 72,207, and the Boston filter is applied to those before billing.
What is the CRD number and why does it matter? It is FINRA's Central Registration Depository ID. Present on 97.6% of rows, it joins this dataset to BrokerCheck and SEC IAPD — employment history, exams, registrations, disciplinary events — without any name matching.
Can I check whether a planner has been disciplined?
Turn on includeDisclosures to fill hasDiscipline and hasBankruptcy from CFP Board's own verification service (~1.0% carry a flag). Measured cost is time, not money: 100 planners without it took 5 seconds, 50 planners with it took 81 seconds. Every checked row also gets a disclosureUrl to the full background page.
Can I find planners who lost their certification?
No. The directory lists only currently-certified professionals, so certificationStatus is "Certified" on every row. Follow crd into BrokerCheck for lapsed or disciplined individuals.
Can I schedule this to track new certifications?
Yes — use the Schedules tab on this Actor. A monthly full run and a diff on cfpId gives you newly certified professionals.
What happens if CFP Board changes its filter list? The Actor reads the live facet vocabulary at the start of every run. A renamed or added service keeps working; an unrecognised one stops the run and prints the current list rather than returning nothing quietly.
Something looks wrong — how do I debug it? Read the run log: it prints the live directory total, the matched total per scope, page-by-page progress, and a final line with rows emitted, duplicates skipped and rows dropped by your filters. Then open an issue on the Issues tab.
Is minInvestableAssets the planner's AUM?
No. It is the minimum a planner will accept from a client, in dollars. Every planner states one (100% fill).
Changelog
| Version | Date | Change |
|---|---|---|
| 0.1.8 | 2026-08-19 | Close-out audit pass. (1) scrapedAt is now declared nullable in the dataset schema like every other field — it is always an ISO timestamp in practice, so this is defensive hardening against a schema-validation-error ever turning a run red; zero behaviour change. (2) Default run memory lowered from 1024 MB to 512 MB — every run now costs you half what it did. Apify bills compute per GB-second, so an over-provisioned Actor charges a multiple for the same work. Measured, not guessed: peak RSS was 52-74 MB across 13 platform runs, and the heaviest case this Actor has — a full 72,468-row directory walk, 725 pages, every id held in the de-duplication set — peaked at 102.7 MB. 512 MB keeps 5x headroom over that worst case and was re-run at the new size to confirm it does not run out of memory. No behaviour change. |
| 0.1.6 | 2026-08-19 | Reliability + billing-honesty pass, all of it measured on live platform runs. (1) Wall-clock budget: the Actor now reads the platform's kill time and stops fetching with room to flush — before this, an unbounded run under a 120-second limit ended TIMED-OUT 1 time in 3 (113 s / 115 s / 122 s); after, 3/3 Succeeded at 62–67 s with data and a status message. (2) No run ends Failed any more: a transient CFP Board outage, an unrecognised filter label, a zero-row filter combination and a changed API contract all end Succeeded with the reason in the status message, and unhandledRejection / uncaughtException nets deliver whatever was already collected. (3) The delivered count is now read from the charging manager instead of the internal counter, so the log and status message state exactly what was stored and billed — a capped run used to report "4,400 emitted" when 4,158 were delivered. (4) The walk now stops as soon as the run's charge cap is reached instead of paying run time for pages that can never be delivered. |
| 0.1 | 2026-08-12 | Every enumerable filter converted to a drop-down read from CFP Board's live facet payload (54 states, 21 services, 10 specialties, 25 languages, 6 asset bands), each labelled with its live count. Form grouped into 7 sections. maxItems default 500 → 100 so the first click is cheap. Field fill and dedupe re-measured on a fresh 2,500-row contiguous walk; firmUrl documented at 0.2%. Boston and Massachusetts counts measured. Both loud-failure paths re-tested. |
Last verified against the live source: 2026-08-20 — 72,468 professionals (up from 72,207 on 2026-08-12; the directory grows by a few dozen a week, so every count in this README is point-in-time), facet vocabularies re-read from the live response, fill and dedupe re-measured, zero-edit run green.
Legal and fair use
This Actor exports public professional-directory information that CFP Board publishes so that consumers can find and vet a planner. It reads a public JSON search endpoint. It does not log in, does not solve CAPTCHAs, does not touch the Cloudflare-protected contact form, and collects no data behind any authentication.
Rows describe identifiable people. You are responsible for complying with CFP Board's Terms of Use, and with CAN-SPAM, TCPA, GDPR/CCPA and any applicable opt-out, do-not-call and privacy law when you contact these professionals or store their data.
CFP®, CERTIFIED FINANCIAL PLANNER™ and the certification marks are owned by Certified Financial Planner Board of Standards, Inc.; this Actor is not affiliated with or endorsed by CFP Board. FINRA® and BrokerCheck® are trademarks of the Financial Industry Regulatory Authority.
Support
Found a missing field, want a new filter, or hit something that looks wrong? Open an issue on the Issues tab — filter requests against fields CFP Board already publishes are usually quick.
If this Actor saved you time, a rating helps other buyers find it.
Keywords: CFP Board scraper · certified financial planner directory · CFP professional list · letsmakeaplan.org scraper · financial advisor leads · financial planner leads · CFP directory export · advisor lead generation · CRD number lookup · FINRA BrokerCheck link · SEC IAPD link · wealth management prospecting · RIA lead list · fintech prospecting · financial advisor database · CFP professionals by state · financial planners California · financial planners New York · financial planners Texas · financial planners Florida · Spanish speaking financial advisor · tax planning advisor list · estate planning advisor list · retirement planning advisor list · divorce financial planner · fee-only advisor data · advisor recruiting data · RIA M&A target list · wealthtech sales leads · advisor CRM enrichment · financial services outbound · certified financial planner API · CFP verification · financial planner phone numbers · advisor LinkedIn profiles