How-to
How to run Mississippi Contractor License Lookup & Leads Scraper (MSBOC)
Step-by-step: the exact input, what each field does, and the rows that come back from MS MSBOC.
You need Mississippi’s licensed contractors as a spreadsheet: every active electrical licence in one county, say, or the whole state for a CRM. The Mississippi State Board of Contractors (MSBOC) answers that question for free on its own search page, 25 rows to a page by default, and it publishes no download file. The roster is large: MSBOC reported 13,188 active licences when we ran this on 2026-10-07. The bigger cost is that classifications, expiry dates and officers are not in the result list at all; each one sits on a separate detail page, one licence at a time. This actor sends your filters to MSBOC, pages through every result and opens each detail page for you.
What you’ll need
Nothing but an Apify account. The actor talks to MS MSBOC directly.
No API key, no proxy and no CAPTCHA. MSBOC’s search answers plain requests, and the proxy setting ships switched off. The only charge is $0.004 per licence returned, plus Apify’s own platform usage.
Step 1: Open the actor
Open Mississippi Contractor License Lookup & Leads Scraper (MSBOC) on the Apify Store and press Try for free. The actor’s own page on this site lists its live health and pricing.
Step 2: Fill in the input
| Field | Type | Required | What it does |
|---|---|---|---|
status | string | no | Which licences to export. ‘Active’ is every currently licensed contractor (13,186 on 2026-10-07). ‘Expired’ is the lapsed list (24,033), useful for win-back or compliance checks. (default active) |
licenseType | string | no | Commercial (Board of Contractors commercial licences) or Residential (residential builders, remodelers and trades). ‘Any’ returns both. (default any) |
classification | string | no | An MSBOC classification by code or name, e.g. ‘E’ (Electrical Work), ‘S123’ (Residential Roofing), ‘Building Construction’, ‘Residential Builder’. An exact class name picks… |
classifications | array | no | Several classifications in ONE run. Combined with ‘Classification’ if you fill both. A licence returned by two searches is returned (and billed) once. (default []) |
county | string | no | Mississippi county, e.g. ‘Hinds’, ‘DeSoto County’, ‘harrison’. MSBOC assigns the county from the ZIP of the licensee’s address, so out-of-state firms are not under any county.… |
counties | array | no | Several counties in ONE run, e.g. Hinds, Madison and Rankin. Combined with ‘County’ if you fill both. (default []) |
city | string | no | City of the licensee’s address. MSBOC matches the start of the city name (‘JACK’ matches JACKSON). |
cities | array | no | Several cities in ONE run. (default []) |
zipCode | string | no | A 5-digit ZIP code of the licensee’s address. |
zipCodes | array | no | Several 5-digit ZIP codes in ONE run. Anything that is not 5 digits is dropped (logged). (default []) |
businessName | string | no | Part of the company name, e.g. ‘ELECTRIC’ or ‘Smith’. MSBOC matches it anywhere in the name. |
businessNames | array | no | Several company-name searches in ONE run. (default []) |
includeDetails | boolean | no | Fetch each licence’s MSBOC detail page to add its classifications, qualifying names, officers, first-issue and expiry dates, fax, minority flag and (for Mississippi addresses)… (default True) |
maxResults | integer | no | Cap on licences returned PER search (each county x classification x city x ZIP x name combination), so adding a county never truncates the ones after it. The whole active… (default 500) |
The field first-time users get wrong is classification, because a word can match more than one class. A code (“E”, “S123”) or an exact class name picks exactly one. Anything else searches every class with a word starting with what you typed: “roof” in Hinds County ran two searches on 2026-10-07, Residential ROOFING (9 licences) and Commercial ROOFING, SHEETMETAL AND SIDING (3). The code “B” is Building Construction on commercial licences and Residential Builder on residential ones, so set licenseType if you mean only one.
The other one is maxResults, which caps each search rather than the run. The default of 500 is fine for a county, but a statewide export with no filters needs 100000, or you get the first 500 of 13,188 sorted by company name. status takes one value per run; for the lapsed list, run again with “expired”, which MSBOC counted at 24,031 on 2026-10-07.
A working input:
{
"county": "Hinds",
"classification": "E"
}
Step 3: Run it
Press Start. Rows are pushed to the dataset as they’re found, so the run log fills in as it works.
The input above returned 29 active Electrical Work licences on 2026-10-07, and the log line reads “MSBOC reports 29, returned 29”, so you can see the source’s own total next to what you got. Detail pages are fetched six at a time: our local run of Hinds, Madison and Rankin together (85 licences) took 5.3 seconds with details on. With details off, the whole active roster came back in 4.5 seconds. Zero rows with no notice means MSBOC itself said “No records were found matching your criteria”. A single free row with a notice means a filter value was not recognised (a misspelt county is dropped, never widened to the whole state) or MSBOC did not answer.
Step 4: Read the output
Each run returns a labelled table, not raw JSON:
Every row looks like this, a real row from a real run:
{
"business_name": "LEFLORE CONSTRUCTION LLC",
"license_number": "19113-MC",
"license_type": "Commercial",
"status": "Licensed - Active",
"classifications": [
"BUILDING CONSTRUCTION",
"ELECTRICAL WORK",
"HIGHWAY, STREET AND BRIDGE CONSTRUCTION",
"MECHANICAL WORK"
],
"qualifying_names": [
"MARCO LEFLORE"
],
"officers": [
"KERRY LEFLORE (PRESIDENT)",
"MARCO LEFLORE (VICE-PRESIDENT)"
],
"issue_date": "09/07/2011",
"expiration_date": "09/29/2027",
"phone": "601-214-0125",
"address": "4670 MCWILLIE DRIVE",
"city": "JACKSON",
"address_state": "MS",
"zip_code": "39206",
"county": "Hinds",
"state": "MS",
"minority": "Yes",
"details_status": "ok",
"source_url": "https://search.msboc.us/Detail.cfm?ContractorID=22467&ContractorType=Commercial&varDataSource=BOC"
}
| Field | Example value | Meaning |
|---|---|---|
business_name | LEFLORE CONSTRUCTION LLC | Company name as licensed by MSBOC |
license_number | 19113-MC | MSBOC licence number (commercial numbers carry a suffix such as -MC or -SC) |
license_type | Commercial | Commercial or Residential |
status | Licensed - Active | The status searched, e.g. ‘Licensed - Active’ |
classifications | ["BUILDING CONSTRUCTION", "ELECTRICAL WORK", "HIGHWAY, STREET AND BRIDGE CONSTRUCTION", "MECHANICAL WORK"] | Classes the licence holds, e.g. ELECTRICAL WORK, RESIDENTIAL BUILDER (details on) |
qualifying_names | ["MARCO LEFLORE"] | Qualifying person(s) for those classes (details on) |
officers | ["KERRY LEFLORE (PRESIDENT)", "MARCO LEFLORE (VICE-PRESIDENT)"] | Officers as ‘NAME (TITLE)’ (details on) |
issue_date | 09/07/2011 | First issue date, MM/DD/YYYY (details on) |
Most people come for phone and expiration_date. Phone is on 13,150 of the 13,188 active licences, but MSBOC stores it as typed: 10,732 look like 601-214-0125, 1,628 like (601)922-3575, 677 are ten bare digits, and a few dozen are stranger still, so normalise the column before you dial from it. There is no email anywhere on MSBOC’s pages, so no row carries one. Plan for phone and mail.
The address needs care too. Only 7,399 of the active licensees have a Mississippi address; Tennessee (947), Louisiana (943) and Alabama (838) lead the rest, and an out-of-state firm has no county, so it never appears in a county search. Statewide, 2,074 addresses are PO boxes. classifications, both dates, officers and county exist only when details are on; details_status reads “ok” when the detail page was read, and “failed” on a row whose page could not be. Key your rows on license_type plus license_number, because the number alone repeats: 13,188 active rows carry 13,185 distinct numbers.
Step 5: Export it
Open the Dataset tab and export to CSV, JSON or Excel, or pull the same rows from the API, which is what you want if this is going to run on a schedule.
What it costs
$0.004 per licence returned, plus Apify’s own platform usage. The Hinds County electrical run above is 29 rows, about $0.12. Hinds, Madison and Rankin together came to 85 rows, $0.34. The default cap of 500 is $2.00, and the whole active roster at 13,188 rows is $52.75. The price is the same with details on or off. Notice rows, for an outage or an unusable filter, cost nothing, and a licence matched by two of your searches is billed once.
Where the data comes from
This reads MS MSBOC directly. The target is MSBOC’s search results page, one plain GET with every filter in the URL (up to 5,000 rows per page), plus each licence’s detail page for classifications and dates. Every night a canary runs this actor against that live source and checks that Hinds County Electrical Work still returns at least 20 licences, each with a licence number, type, street address, city, ZIP and status: what “verified” means.
MSBOC’s QuickSearch at search.msboc.us is public and free, and for 29 electricians in one county it is a perfectly good tool: pick the county and the class, set Rows Per Page to 250, and the list fits on one page. What it will not do is export, and every expiry date or officer list means opening that licence’s page by hand. Two quirks catch people who script it themselves: a search that matches exactly one licence jumps straight to that licence’s page instead of a list, and MSBOC’s ZIP table spells some Claiborne County ZIPs “CALAIBORNE”, which the actor searches as well.
See it used
List Electrical Contractors in Hinds County, Mississippi builds a bid list of electrical subs around Jackson: 85 active licences across three counties, each with a phone and an expiry date.
For a state that publishes email with the licence, Virginia Contractor License Lookup exports DPOR’s whole roster. Working next door in Tennessee, use Tennessee Contractor License Lookup.
Last updated 2026-10-07