NMLS Consumer Access Scraper — Licenses & Contacts
Pricing
from $1.00 / 1,000 record scrapeds
NMLS Consumer Access Scraper — Licenses & Contacts
Scrape NMLS Consumer Access for mortgage companies, MLOs, and branches — state licenses with statuses and dates, regulatory disclosures with PDF links, trade names, and sponsor/branch relationships. Search by name, NMLS ID, or state; CAPTCHA solved automatically. Clean JSON/CSV output.
Pricing
from $1.00 / 1,000 record scrapeds
Rating
0.0
(0)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
0
Bookmarked
24
Total users
7
Monthly active users
7 hours ago
Last modified
Categories
Share
Turn NMLS Consumer Access into structured mortgage-licensing data. Scrape any company, individual (MLO), or branch from nmlsconsumeraccess.org — legal name, NMLS ID, addresses, every state license with status and dates, regulatory-action disclosures with PDF links, trade names, and sponsor/branch relationships. Search by name, look up NMLS IDs directly, filter to branches, or sweep a whole state. Optional public-email enrichment. JSON or CSV out, priced per result.
| Input | Row(s) emitted |
|---|---|
| Name / search query | One row per matching company, MLO, or branch |
| NMLS ID | The matching entity (company, individual, or branch), or a lookup_status: not_found row if the ID misses |
| Sponsoring company NMLS ID | The company plus each sponsored MLO |
| State code | Matching entities in that state (pair with entity type) |
| Detail or search URL | The entity on that page, or every hit from that search |
Pure HTTP (impit + cheerio). CAPTCHA is solved automatically. No browser.
Why use this scraper?
NMLS Consumer Access is the public mortgage-licensing registry, but it is gated behind a CAPTCHA and has no export.
- Five seeding modes. Search by company or person name, fetch exact NMLS IDs, pull a company's sponsored MLO roster, sweep a state, or paste detail-page URLs.
- CAPTCHA handled for you. BotDetect is solved once per session and reused for every request in the run.
- Full state-license tables. Regulator, license name/number, status, issue date, status date, renewal year, and trade names on that license. Large lenders return 90–180 license rows each.
- Regulatory disclosures with PDF links. Consent orders, final orders, settlements — each with a document URL.
- Relationship expansion. Follow an individual's sponsoring companies and a company's branches and sponsored MLOs (
maxSeedDepth).by_company_employeesexpands MLOs even when depth is 0. - Optional contact emails.
enrichEmails: trueattaches a publiccontact_emailwhen one is found ($0.05 only on a hit). - Clean exports. One row per entity, JSON + CSV, no duplicates within a run.
Overview
Built for compliance teams, lender-vetting pipelines, recruiters, and anyone who needs a machine-readable copy of what nmlsconsumeraccess.org already shows a browser. Each dataset row is one entity. Companies carry corporate fields and a branch list URL; individuals carry employers and sponsor refs; branches carry the parent company and their own licenses.
Supported inputs
Pick a mode and fill in the matching field.
| Mode | Input field | Behaviour |
|---|---|---|
by_name | names | Runs an NMLS search per query. Add a city/state/ZIP to narrow (e.g. Rocket Mortgage Detroit MI) — NMLS rejects overly broad searches. |
by_id | nmlsIds | Fetches each ID's detail page directly. Each ID is tried as company → individual → branch (or restricted via entityType, including BRANCH). A miss still writes a row with lookup_status: "not_found". |
by_company_employees | sponsoringCompanyIds | Fetches each company, runs NMLS search on its name across its licensed states (or states), and keeps every individual whose detail page names that company as sponsor. Each MLO row carries sponsoringCompanyId. Cap with maxItems. |
by_state | states | Two-letter codes (TX, CA). Searches the whole state; pair with entityType to keep it focused. |
by_url | startUrls | Exact NMLS URLs — detail pages like https://www.nmlsconsumeraccess.org/EntityDetails.aspx/COMPANY/3030 or search URLs like https://www.nmlsconsumeraccess.org/Home.aspx/SubSearch?searchText=.... |
Not supported: hosts outside nmlsconsumeraccess.org; licensee-only NMLS portal pages.
Use cases
| Team | What they build |
|---|---|
| Lead generation / sales | Contact lists of licensed mortgage companies and MLOs by state, with phone, email, and website |
| Compliance & risk | License-status monitoring and disclosure (regulatory-action) alerts on counterparties |
| Fintech / lending platforms | Partner-vetting pipelines keyed on NMLS ID with license coverage per state |
| Market research | State-by-state maps of active mortgage lenders, brokers, and servicers |
| Recruiters | MLO sourcing with sponsoring-company relationships |
| Journalists / researchers | Datasets on enforcement actions and license surrenders |
How it works
- Solve the gate once. NMLS redirects every request to a BotDetect CAPTCHA page. The actor solves it and keeps the unlocked session cookie for the whole run.
- Seed from your names / IDs / states / URLs — searches go through NMLS's own JSON search endpoint.
- Fetch each entity's detail page in parallel over the shared session, re-solving if the session expires.
- Parse company / individual / branch layouts into one structured row each.
- Optionally expand to related entities (sponsors, branches, sponsored MLOs) up to
maxSeedDepthhops andmaxSeedExpansionsentities.by_company_employeesalways walks the MLO roster. - Optionally enrich a public contact email when
enrichEmailsis on. - Push one row per entity to the dataset.
Input configuration
| Field | Type | Required | Notes |
|---|---|---|---|
mode | string | no | by_name (default) / by_id / by_state / by_url / by_company_employees |
names | array | for by_name | Search queries. Prefill: Rocket Mortgage Detroit MI |
nmlsIds | array | for by_id | Exact NMLS IDs. Prefill: 3030 |
sponsoringCompanyIds | array | for by_company_employees | Company NMLS IDs whose MLO roster you want. Prefill: 3030 |
states | array | for by_state | Two-letter codes (TX, CA) |
entityType | string | no | "" (any), COMPANY, INDIVIDUAL, or BRANCH |
startUrls | array | for by_url | Detail or SubSearch URLs |
includeDisclosures | boolean | no | Default true |
maxSeedDepth | integer | no | 0–3, default 0 |
maxSeedExpansions | integer | no | Default 100 |
enrichEmails | boolean | no | Default false. Bills contact-email only when an email is found |
maxItems | integer | no | Default 1000 |
maxConcurrency | integer | no | Default 5 |
proxy | object | no | Default Apify RESIDENTIAL |
Example input
Fetch two lenders and map their branches:
{"mode": "by_id","nmlsIds": ["330511", "1850"],"maxSeedDepth": 1,"maxSeedExpansions": 50,"maxItems": 100}
Companies matching a name search:
{"mode": "by_name","names": ["Better Mortgage New York NY"],"entityType": "COMPANY","maxItems": 20}
A single branch by NMLS ID:
{"mode": "by_id","nmlsIds": ["2708833"],"entityType": "BRANCH","maxItems": 1}
MLOs sponsored by a company:
{"mode": "by_company_employees","sponsoringCompanyIds": ["3030"],"maxItems": 50}
Output overview
Each entity is one dataset row with entityType set to COMPANY, INDIVIDUAL, or BRANCH. All three share identity, a split address (city, state, zip, addressLine2 plus the original streetAddress), stateLicenses[], license rollups, and disclosures[]. Companies add corporate fields (businessStructure, sponsoredMlos, trade-name history, branchListUrl). Individuals add employers[], officeLocations[], and sponsor refs in relatedRefs[]; since MLO pages carry no street-address field, an individual's streetAddress / city / state / zip come from their Main office (or the first listed one). Successful lookups set lookup_status: "found"; an ID that matches no type writes a short not_found row. When enrichEmails is on, a found address lands in contact_email.
Output samples
One company row, trimmed (this lender returns 93 license entries; two shown):
{"nmlsId": "330511","entityType": "COMPANY","name": "Better Mortgage Corporation","streetAddress": "1 World Trade Center 80th Floor New York, NY 10007","city": "New York","state": "NY","zip": "10007","addressLine2": "80th Floor","lookup_status": "found","mailingAddress": "1 World Trade Center 80th Floor New York, NY 10007","phone": "415-523-8837","email": "licensingteam@better.com","website": ["www.better.com", "www.neohomeloans.com"],"otherTradeNames": ["Better Mortgage", "NEO Home Loans"],"priorOtherTradeNames": ["Avex Funding Corporation", "Better", "Better.com"],"priorLegalNames": ["Avex Funding Corporation"],"sponsoredMlos": "353","fiscalYearEnd": "12/31","formedIn": "California, United States","dateFormed": "02/25/2003","businessStructure": "Corporation","regulatoryActions": "Yes","stateLicensesCount": 93,"stateLicensesActiveCount": 80,"hasRegulatoryActions": true,"licenseTypes": ["Mortgage Banker License", "Mortgage Broker/Lender License - Other Trade Name #1"],"stateLicenses": [{"regulator": "Arizona","licenseName": "Mortgage Banker License","authorizedToConductBusiness": "Yes","licenseNumber": "BK-0942146","originalIssueDate": "05/03/2017","status": "Approved","statusDate": "09/30/2025","renewedThrough": "2026","otherTradeNames": "Better Mortgage; NEO Home Loans"},{"regulator": "Alaska","licenseName": "Mortgage Broker/Lender License - Other Trade Name #1","authorizedToConductBusiness": "No","licenseNumber": "AK330511","originalIssueDate": "08/04/2020","status": "Voluntary Surrender","statusDate": "07/14/2022","renewedThrough": "None"}],"disclosures": [{"title": "Consent Order","url": "https://www.nmlsconsumeraccess.org/EntityDetails.aspx/Artifact/Other.pdf?q=277502-368825"},{"title": "Settlement","url": "https://www.nmlsconsumeraccess.org/EntityDetails.aspx/Artifact/Settlement.pdf?q=308059-398860"}],"branchListUrl": "https://www.nmlsconsumeraccess.org/EntityDetails.aspx/Branches/330511","sourceUrl": "https://www.nmlsconsumeraccess.org/EntityDetails.aspx/COMPANY/330511","scrapedAt": "2026-07-22T21:32:55.719Z"}
Key output fields
| Group | Fields |
|---|---|
| Identity | nmlsId, entityType (COMPANY / INDIVIDUAL / BRANCH), name, lookup_status (found / not_found), sourceUrl, scrapedAt |
| Contact | streetAddress, city, state, zip, addressLine2, mailingAddress, phone, tollFreeNumber, fax, email, website[] |
Enrichment (when enrichEmails: true) | contact_email, contact_website, emailEnrichment.{website, emails, source, confidence} |
| Names history | otherTradeNames[], priorOtherTradeNames[], priorLegalNames[], otherNames[] |
| Corporate (companies) | businessStructure, formedIn, dateFormed, fiscalYearEnd, stockSymbol, sponsoredMlos, branchListUrl |
| Licenses | stateLicenses[], stateLicensesCount, stateLicensesActiveCount, licenseTypes[], hasRegulatoryActions |
| Disclosures | regulatoryActions, selfReportedDisciplinaryActions, disclosures[].{title, url} |
| Relationships | employers[] and officeLocations[].{company, companyNmlsId, type, streetAddress, city, state, zip, startDate} (individuals), relatedRefs[].{entityType, id, url}, sponsoringCompanyId (MLOs reached through a company roster) |
Pricing
| Event | When | Rate |
|---|---|---|
| Actor start | Once per run, per GB of memory | $0.10 |
| Record scraped | Each dataset row (company, MLO, or branch) | $0.001 |
| Contact email found | Only when enrichEmails is on and a public email is found | $0.05 (billed as additional-data units until the named contact-email event can be registered on 7 Oct 2026) |
Cap spend with maxItems. Enrichment is never billed on a miss.
What makes this richer than the competition
Compared with jungle_synthesizer/nmls-consumer-access-crawler:
| Capability | Other NMLS crawler | This actor |
|---|---|---|
| CAPTCHA after a successful solve still dropping the record | Reported by their users (closed issues, May 2026) | Session is re-solved transparently; cloud smoke on 330511 returned 93 licenses |
| Company → sponsored MLO roster | by_company_employees | Same mode (sponsoringCompanyIds), sponsor confirmed on each detail page, sponsoringCompanyId on every MLO row, plus MLO expansion when maxSeedDepth >= 1 |
| Split address + license rollups | city / state / zip | Same, plus addressLine2, stateLicensesCount, stateLicensesActiveCount, hasRegulatoryActions |
| Missed ID is visible | lookup_status | lookup_status: "not_found" row instead of a silent skip |
| Branch-only lookup | Search/company/MLO focused | entityType: "BRANCH" plus branch expansion from a company |
| Contact email enrichment | Not on the Store card | Opt-in enrichEmails, billed only on a hit |
| Public issues | Two closed "record not found" bugs | None filed |
Same start + per-record price ($0.10 + $0.001).
Notes & limitations
- NMLS rejects overly broad name searches. Add a city, state, or ZIP.
- Datacenter proxies are blocked. Keep the default residential group.
- Only public Consumer Access pages are scraped — no NMLS portal login, no non-public data.
- Local OCR almost never solves BotDetect; the run uses CapSolver behind the scenes.
FAQ
How does the actor get past the NMLS CAPTCHA? NMLS serves a BotDetect image CAPTCHA before any data page. The actor solves it at run start and reuses the unlocked session, re-solving if the session expires. You do not configure a solver.
Which entity types are returned?
Companies, individuals (MLOs), and branches. In by_id mode each ID is tried as company → individual → branch until one matches. Set entityType to COMPANY, INDIVIDUAL, or BRANCH to skip the guessing.
Why do my name searches return nothing?
NMLS caps result sets server-side. Narrow the query — e.g. Better Mortgage New York NY.
How do I get a company's branches or an MLO's employer?
Set maxSeedDepth: 1. Companies expand to branches and sponsored MLOs; individuals expand to sponsoring companies. maxSeedExpansions caps the total.
How do I pull the MLOs a company sponsors?
Set mode: "by_company_employees" and put the company NMLS ID in sponsoringCompanyIds. NMLS has no roster page, so the actor searches the company name as an individual query (per licensed state, then per state and first name when NMLS refuses a query as too broad) and keeps only people whose detail page lists that company under its sponsors. The company row is included; each MLO row has sponsoringCompanyId. For a sponsor with thousands of MLOs the result is a sample bounded by maxItems, not the full list. Pass states to focus the sweep.
What if an NMLS ID does not exist?
The run still writes a row: lookup_status: "not_found", with the ID you asked for. Hits use lookup_status: "found".
What does enrichEmails cost?
Nothing unless a public email is found. A hit charges the contact-email event ($0.05). The NMLS page email (email) is always included when the registry lists one, at no extra charge.
Do I need my own proxy?
No. The default Apify residential proxy works. Switching away from RESIDENTIAL will typically break the run.
Can it access licensee-only or authenticated NMLS data? No. Only the public Consumer Access pages.
How do I limit cost?
Set maxItems. The actor stops queuing new entities once the cap is reached.
Support
- Issues: the Issues tab on the actor's Apify Console page
- Website: https://muhamed-didovic.github.io/
- Email: muhamed.didovic@gmail.com
Additional services
Custom output shape, additional fields, one-off datasets, or a similar scraper for another licensing registry: muhamed.didovic@gmail.com. API access (usage fee only, no Apify fee) on request.
Explore more scrapers
Other scrapers and actors at memo23's Apify profile — job boards, real estate, directories, social, and more.
🤖 For AI Agents & LLM Apps
Compact reference for agents calling this actor via the Apify MCP server or the Apify API (actor: memo23/nmls-scraper).
Purpose: look up US mortgage companies, loan originators (MLOs), and branches in the NMLS Consumer Access registry, with state licenses and regulatory disclosures.
Minimal input:
{ "mode": "by_id", "nmlsIds": ["330511"], "maxItems": 1 }
Output: one dataset row per entity — nmlsId, lookup_status, entityType, name, streetAddress, city, state, zip, phone, email, website, otherTradeNames, businessStructure, sponsoredMlos, stateLicenses[], stateLicensesCount, hasRegulatoryActions, disclosures[] ({title, url}), sourceUrl. Optional: contact_email when enrichEmails is true.
Company MLO roster: { "mode": "by_company_employees", "sponsoringCompanyIds": ["3030"], "maxItems": 50 }
Behaviors an agent should know:
- Always set
maxItems. An uncapped state sweep can be thousands of rows. - The actor solves NMLS's CAPTCHA itself (adds about 10–60 s at run start).
- Requires residential proxy (the default is correct).
- Broad name searches are rejected by NMLS — include a city or state in
names. - Billing: $0.10 per start (per GB) + $0.001 per row.
enrichEmailsadds $0.05 only when an email is found. - One row per entity;
entityTypetells you which parser produced it.
⚠️ Disclaimer
This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by the Nationwide Multistate Licensing System (NMLS), the State Regulatory Registry LLC (SRR), the Conference of State Bank Supervisors (CSBS), or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.
The scraper accesses only publicly available pages on nmlsconsumeraccess.org — the same consumer-facing registry data anyone can view in a browser. No authenticated NMLS portal content, licensee-only features, or non-public data is accessed. Users are responsible for ensuring their use complies with nmlsconsumeraccess.org's Terms of Use, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation.
SEO Keywords
nmls scraper, nmls consumer access scraper, scrape nmls, nmls api, nmls data export, nmls license lookup api, mortgage license data, mortgage company license scraper, mlo license scraper, mortgage loan originator data, nmls id lookup, state mortgage license database, mortgage lender verification, mortgage broker license data, loan officer license lookup, mortgage compliance data, nmls regulatory actions data, mortgage industry dataset, mortgage lead generation data, nmls branch locations data, mortgage licensing api alternative