How-to
How to run Arizona Contractor License Lookup & Leads Scraper (ROC)
Step-by-step: the exact input, what each field does, and the rows that come back from the Arizona Registrar of Contractors.
You want Arizona contractors from the Registrar of Contractors (ROC), either a few you need to check or a list you need to call, and ROC gives you two half-answers. Its contractor search shows a phone number and every licence status, but it answers one search at a time and stops at about 1,000 contractors: search all of Phoenix and you get 253, out of 9,162 active Phoenix licences. Its Posting List has every active licence (58,184 in the file dated 2026-10-07) with a street address, but no phone, as a 12 MB CSV. This actor does both jobs. A lookup runs your licence numbers or names through the search. An export filters the Posting List and adds each licence’s phone and principals from the search, matched by licence number.
What you’ll need
Nothing but an Apify account. The actor talks to ROC’s two public sources directly.
No API key and no CAPTCHA. One thing is unusual: ROC’s Posting List sits behind a Cloudflare check that refuses Apify’s datacenter IPs, so an export downloads it through Apify’s residential proxy, which is the input’s default. That download is about 11.4 MB of residential traffic, roughly $0.09 of Apify platform usage per export run, billed to your Apify account like any other usage. Lookups never use the proxy.
Step 1: Open the actor
Open Arizona Contractor License Lookup & Leads Scraper (ROC) 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 |
|---|---|---|---|
query / queries | string / array | no | Licence numbers (‘234021’ or ‘ROC 234021’), business names, or a person’s name written first then last. Filling this makes the run a lookup. |
classification / classifications | string / array | no | Export filter: an ROC class code (‘R-42’, ‘CR-11’, ‘B’, ‘KB-1’) or a word from the class name (‘roofing’, ‘electrical’). |
licenseClassType / licenseClassTypes | string / array | no | Export filter: Residential, Commercial, Dual, General or Specialty. |
city / cities | string / array | no | Export filter: mailing-address city, exact match ignoring case. |
zipCode / zipCodes | string / array | no | Export filter: 5-digit mailing ZIP. |
nameFilter / nameFilters | string / array | no | Export filter: text in the business name, DBA or qualifying party. |
arizonaAddressesOnly | boolean | no | Export filter: drop licences with an out-of-state mailing address. |
includePhone | boolean | no | Export: match each licence to the search for phone and principals. (default true) |
maxResults | integer | no | Export: cap for the whole run (default 500). Lookup: cap per query (default 50). Max 100000. |
proxyConfiguration | object | no | Used only for the export download, only after a direct attempt is refused. (default: Apify residential, US) |
The field that decides everything is query. Fill it and the run is a lookup: ROC’s search, every status, one result list per number or name. Leave it empty and the run is an export of active licences, filtered by the other fields. A lookup ignores the export filters, so {"query": "Arcadia Roofing", "city": "Tucson"} still returns both Arcadia Roofing licences, which are filed in Phoenix.
The second is classification. A code is exact: R-42 is residential roofing only, 7 of the 244 Phoenix roofing licences. A word matches every scope: roofing takes C-42 (commercial), R-42 (residential) and CR-42 (dual) together. In Arizona most specialty contractors hold the dual class: 236 of those 244 Phoenix roofers are CR-42, so R-42 alone misses nearly all of them.
A working input:
{
"classification": "roofing",
"city": "Phoenix",
"maxResults": 500
}
Step 3: Run it
Press Start. The run log says how many licences matched before anything is returned, then how many it matched to a phone.
On Apify on 2026-10-11 that input took 48 seconds: the direct download was refused (posting page HTTP 403), the residential fallback read the 58,184 licences in 5.9 seconds, the log said “244 of 58184 active licences match”, and the phone match covered 244 of 244 in 84 search calls. The empty default input returns the first 500 licences alphabetically and took 159 seconds, most of it matching 500 licences spread across 73 classes. A lookup of a licence number and a business name took 7 seconds. A name that matches nothing is logged as “no match” and adds no row; a filter value it cannot recognise is dropped with a log line, and if none of your values for a filter is usable you get one free row saying so rather than the whole state.
Step 4: Read the output
Each run returns a labelled table, not raw JSON:
Every row looks like this, a real row from that run:
{
"license_number": "234021",
"business_name": "Arcadia Roofing, LLC",
"dba_name": null,
"classification": "CR-42",
"classification_detail": "CR-42 Roofing",
"license_class_type": "Specialty Dual",
"status": "Active",
"person_name": "Tommy Louis Leale",
"principals": [
"Tommy Louis Leale (Member;Qualifying Party)"
],
"phone": "(602) 840-7663",
"address": "3008 N. 44th Street",
"city": "Phoenix",
"address_state": "AZ",
"zip_code": "85018",
"issue_date": "2007-06-16",
"expiration_date": "2027-06-30",
"matched_by": "export",
"license_type": "Contractor License",
"state": "AZ",
"source_url": "https://roc.az.gov/posting-list"
}
| Field | Example value | Meaning |
|---|---|---|
license_number | 234021 | ROC licence number, six digits |
classification_detail | CR-42 Roofing | Class code and name |
status | Active | Always Active on an export; any status on a lookup |
person_name | Tommy Louis Leale | Qualifying party |
principals | Tommy Louis Leale (Member;Qualifying Party) | Everyone on the licence, with roles |
phone | (602) 840-7663 | Business phone from ROC’s search |
Most people came for phone. On the full state on 2026-10-11 it was filled on 57,999 of 58,184 active licences (99.7%). Of the 185 without one, 7 licences had no account in the search (all of them numbers issued in the last few years), and on the other 178 the search itself holds no phone. A very large export that runs out of its time budget also leaves phone null on the rows it did not reach.
Two other things to know. person_name is null on 3,102 licences where ROC files “QP Exempt” or “Could not find QP Name”; those are placeholders, not people, so the actor drops them, and principals still names the people on 3,090 of those 3,102. Lookup rows come from the search side, so they carry city, state and ZIP but no street address and no issue or expiry date; an export row has all of them.
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 Phoenix roofing run above is 244 rows, so $0.98, and its platform usage was $0.09, almost all of it the residential download. The default export is 500 rows ($2.00). Every active licence in the state is 58,184 rows ($232.74), and took 464 seconds when we ran it on 2026-10-11. A lookup costs $0.004 per licence it returns and uses no proxy. Rows explaining an outage or an unrecognised filter are free.
Where the data comes from
Exports read ROC’s Posting List, the CSV of current active licences linked from roc.az.gov, which ROC refreshes every few days (the 2026-10-11 runs read the file dated 2026-10-07). Lookups and the phone match use ROC’s public Contractor Search on its Salesforce portal, the page in the screenshot below. Every night a canary runs this actor against both live sources and checks that a Flagstaff roofing export still returns at least 10 licences, with phone on at least 80% of them: what “verified” means.
If you need a handful of contractors, the search page is free and fine. The work starts when you need a list: the search stops at about 1,000 results and applies its city filter after that cutoff, and the Posting List has no phone column, so a call list means downloading the CSV and looking up its licences one search at a time. For Phoenix roofing, that is 244 searches.
See it used
Export Phoenix, Arizona Roofing Contractors builds a call list of the 244 active roofers with a Phoenix mailing address. Verify Arizona ROC Contractor Licenses checks a vendor list’s licence numbers and names for suspended, expired or revoked licences.
For Arizona’s western neighbour, Nevada Contractor License Lookup & Verify (NSCB) does the same lookup-or-export job against Nevada’s State Contractors Board.
Last updated 2026-10-11