Arizona ROC Contractor License Scraper avatar

Arizona ROC Contractor License Scraper

Pricing

from $2.19 / 1,000 license records

Go to Apify Store
Arizona ROC Contractor License Scraper

Arizona ROC Contractor License Scraper

Look up Arizona Registrar of Contractors licenses by number, company, qualifying party, or city. Get status, bond, classification, personnel, and complaint history. Export as JSON, CSV, or Excel.

Pricing

from $2.19 / 1,000 license records

Rating

0.0

(0)

Developer

ParseBird

ParseBird

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Arizona ROC Contractor License Scraper

Look up Arizona Registrar of Contractors (AZ ROC) license records by license number, company name, qualifying party, or city. The Arizona ROC Contractor License Scraper pulls license status, bond details, classification, personnel, and complaint history for any Arizona contractor, with no login and no AZ ROC API key.

Search by license number, company, qualifying party, or city, filter by classification, status, and type, then get full bond, personnel, and complaint-history data straight from AZ ROC's own records.

Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

Actor: parsebird/az-roc-contractor-license-scraper (Apify). Looks up Arizona Registrar of Contractors (AZ ROC) contractor licenses. Call with ApifyClient.
Input JSON fields: licenseNumbers: string[] — exact ROC license numbers, e.g. ["333318"] (leading zeros added automatically to 6 digits); companyNames: string[] — partial business name matches; qualifyingPartyNames: string[] — partial name matches for the individual responsible for the license; cities: array<string> — Arizona cities to search by mailing address; licenseClassification: string — optional classification code, e.g. "C-37" (see the Classification Reference in the README); licenseType: "ALL"|"RESIDENTIAL"|"COMMERCIAL"|"DUAL" (default ALL); licenseStatus: "ALL"|"ACTIVE"|"SUSPENDED"|"EXPIRED"|"REVOKED"|"CANCELLED" (default ALL); maxResultsPerSearch: int (default 0 = unlimited); scrapeDetailPage: bool (default true) — full bond/personnel/complaint data; scrapeComplaints: bool (default true); maxConcurrency: int 1-10 (default 3); proxyConfiguration: object (default residential).
Output: one dataset item per license — licenseNumber, licenseType, licenseStatus, businessName, dbaName, qualifyingParty, entityType,
personnel, primaryClassification, classificationDesc, classifications, city, state, zip, phone, issuedDate, renewedThroughDate,
expirationDate, bondType, bondStatus, bondAmount, bondCompany, bondNumber, bondEffectiveDate, openCases, disciplinedCases,
resolvedCases, complaintCount, complaints, profileUrl, searchQuery, scrapedAt.
Example: { "licenseNumbers": ["333318"], "cities": ["Tucson"], "licenseClassification": "C-37", "licenseStatus": "ACTIVE" }
API: https://api.apify.com/v2/acts/parsebird~az-roc-contractor-license-scraper · Token: https://console.apify.com/account/integrations

What does Arizona ROC Contractor License Scraper do?

The Arizona Registrar of Contractors licenses every contractor legally allowed to work in Arizona. There is no public AZ ROC API — this scraper reads the same public search backend the AZ ROC contractor-search website itself uses. For every matching license it extracts:

  • 🏷️ License identity — number, type, status, business name, DBA name, entity type, and qualifying party.
  • 👥 Personnel — officers, members, partners, and the qualifying party, each with their role.
  • 🧾 Classification — the license's classification code and plain-English description (e.g. C-37 → Plumbing).
  • 💰 Bond information (optional) — bond type, status, amount, surety company, and bond number.
  • ⚠️ Complaint history (optional) — open, disciplined, and resolved case counts for the prior two years, as displayed by AZ ROC.

Common uses: vetting a contractor before hiring, verifying an active license and bond before signing a contract, due-diligence checks for lenders and insurers, and building a local dataset of licensed contractors by city or trade.

Input parameters

ParameterTypeRequiredDefaultDescription
licenseNumbersarrayNo[]ROC license numbers to look up directly. Leading zeros added automatically to make 6 digits. Fastest, most precise mode.
companyNamesarrayNo[]Business names to search. Partial matches accepted. Each name is its own search.
qualifyingPartyNamesarrayNo[]Full name of the qualifying party (format: First Last). Partial names allowed.
citiesarrayNo[]Arizona cities to search by mailing address, e.g. Phoenix, Tucson. Must match AZ ROC's exact spelling on file.
licenseClassificationstringNo""Classification code filter, e.g. B-1, R-11, C-37. See the Classification Reference below.
licenseTypeenumNoALLOne of ALL, RESIDENTIAL, COMMERCIAL, DUAL.
licenseStatusenumNoALLOne of ALL, ACTIVE, SUSPENDED, EXPIRED, REVOKED, CANCELLED.
maxResultsPerSearchintegerNo0Cap records per individual search query. 0 = unlimited.
resultsPerPageenumNo"50"Kept for input compatibility only — see the FAQ for why it has no effect.
scrapeDetailPagebooleanNotrueFetch each license's full bond, complaint, classification, and personnel data.
scrapeComplaintsbooleanNotrueCapture complaint history (requires scrapeDetailPage). AZ ROC only shows the prior two years.
maxConcurrencyintegerNo3Max concurrent requests to AZ ROC's search backend (1-10).
proxyConfigurationobjectNoResidentialApify Proxy settings.

Example inputs

Direct license lookup:

{
"licenseNumbers": ["333318"]
}

City + classification, active only:

{
"cities": ["Tucson"],
"licenseClassification": "C-37",
"licenseStatus": "ACTIVE"
}

Fast list-only crawl by company name:

{
"companyNames": ["Acme Plumbing"],
"scrapeDetailPage": false
}

Full detail with complaint history:

{
"qualifyingPartyNames": ["John Smith"],
"scrapeDetailPage": true,
"scrapeComplaints": true
}

What data can you extract from AZ ROC?

Core fields

FieldDescription
licenseNumberROC license number (e.g. 333318)
licenseTypeResidential, Commercial, Dual, or General Engineering — derived from the classification's own description
licenseStatusActive, Suspended, Expired, Revoked, Cancelled, Inactive, etc.
businessNameLegal business entity name
dbaName"Doing Business As" name where present
qualifyingPartyIndividual responsible for the license
entityTypeAZ ROC's own entity-type label (e.g. LLC, Corporation)
personnelOfficers, members, partners, qualifying party — each with name and role

Classification fields

FieldDescription
primaryClassificationClassification code (e.g. B-1, R-11, C-37)
classificationDescPlain-English description of the classification
classificationsArray of { code, description } — AZ ROC issues each classification as its own separate license number, so this typically holds one entry matching primaryClassification

Address, contact & lifecycle

FieldDescription
city / state / zipBusiness mailing address
phoneFormatted as (XXX) XXX-XXXX when the source has 10 digits
issuedDateFirst-issued date, YYYY-MM-DD
renewedThroughDate / expirationDateAZ ROC exposes a single forward-looking "Renewed Through" date; both fields carry that same value

Bond information (with scrapeDetailPage)

FieldDescription
bondTypeContractor bond type (e.g. Surety)
bondStatusActive, Cancelled, Expired, etc.
bondAmountBond face amount, formatted as $ {amount}
bondCompanySurety company name
bondNumberSurety bond number
bondEffectiveDateBond effective date, YYYY-MM-DD

Complaint history (with scrapeComplaints, last 2 years exposed by AZ ROC)

FieldDescription
openCasesCount of open complaints
disciplinedCasesCount of complaints resulting in discipline
resolvedCasesCount of resolved/settled complaints
complaintCountTotal complaint count
complaintsPer-complaint detail, when any exist

Metadata

FieldDescription
profileUrlDirect link to the license's AZ ROC detail page
searchQueryThe input value that produced this record
scrapedAtISO-8601 timestamp of extraction

Output example

{
"licenseNumber": "333318",
"licenseType": "Dual",
"licenseStatus": "Active",
"businessName": "Mike Robbins Plumbing LLC",
"dbaName": "Phoenix Residential & Commercial Plumbing",
"qualifyingParty": "Tyler Michael Robbins",
"entityType": "LLC",
"personnel": [
{ "name": "Tyler Michael Robbins", "role": "Qualifying Party" },
{ "name": "Michael A Robbins", "role": "Manager;Member" }
],
"primaryClassification": "CR-37",
"classificationDesc": "Plumbing",
"classifications": [{ "code": "CR-37", "description": "Plumbing" }],
"city": "Apache Junction",
"state": "AZ",
"zip": "85120",
"phone": "(480) 529-4852",
"issuedDate": "2021-05-12",
"renewedThroughDate": "2027-05-31",
"expirationDate": "2027-05-31",
"bondType": "Surety",
"bondStatus": "Active",
"bondAmount": "$ 6,750",
"bondCompany": "RLI Insurance Company",
"bondNumber": "LSM1483204",
"bondEffectiveDate": "2021-05-04",
"openCases": 0,
"disciplinedCases": 0,
"resolvedCases": 0,
"complaintCount": 0,
"profileUrl": "https://azroc.my.site.com/AZRoc/s/contractor-search?licenseId=a0o8y0000004CYXAA2",
"searchQuery": "333318",
"scrapedAt": "2026-09-05T14:40:46.584Z"
}

Download the dataset as JSON, CSV, Excel, HTML, or XML from the Storage tab or the Apify API.

Use cases

  • Pre-hire vetting — confirm a contractor's license is Active and bonded before signing a contract.
  • Lender / insurer due diligence — check license status, classification, and complaint history in bulk.
  • Market research — pull every licensed contractor for a trade classification or city.
  • Compliance monitoring — track qualifying parties and personnel across multiple licenses.

How it works

  1. Search — each licenseNumbers, companyNames, qualifyingPartyNames, or cities entry runs as its own search against AZ ROC's contractor-search backend.
  2. Flatten — each matched business can hold multiple licenses; the scraper emits one row per license.
  3. FilterlicenseStatus, licenseType, and licenseClassification are applied precisely on the client side (see the FAQ for why).
  4. Enrich (optional) — with scrapeDetailPage on, each license's own detail record is fetched for bond, personnel, and (with scrapeComplaints) complaint history.
  5. Rows stream to the dataset, deduplicated across all searches by license.

How much does it cost to scrape AZ ROC?

This actor is pay per result — charged once per license record saved to the dataset, regardless of whether scrapeDetailPage is on.

PlanPrice per 1,000 licenses
Free$2.99
Bronze$2.79
Silver$2.49
Gold$2.19

A small platform Actor start fee also applies per run. Turn scrapeDetailPage off for a faster, list-only crawl at the same per-row price. Apify's monthly free platform usage covers small runs.

How to look up AZ ROC contractors

  1. Click Try for free and sign in to Apify.
  2. Enter one or more license numbers, company names, qualifying party names, or cities.
  3. Optionally set a classification code, license type, or license status filter.
  4. Toggle Scrape detail page and Scrape complaints for full bond and complaint data.
  5. Click Start, then watch rows appear in the Output tab.
  6. Export from Storage, or pull results via the API.

Run it via API

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("parsebird/az-roc-contractor-license-scraper").call(run_input={
"cities": ["Tucson"],
"licenseClassification": "C-37",
"licenseStatus": "ACTIVE",
})
for lic in client.dataset(run["defaultDatasetId"]).iterate_items():
print(lic["businessName"], "-", lic["licenseNumber"], "-", lic["licenseStatus"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('parsebird/az-roc-contractor-license-scraper').call({
licenseNumbers: ['333318'],
scrapeDetailPage: true,
scrapeComplaints: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Schedule recurring runs, add webhooks, or push results to Google Sheets, Slack, Zapier, and Make with Apify integrations.

Classification Reference

AZ ROC uses a letter-prefix classification system. The actor returns the raw code plus a plain-English description in primaryClassification / classificationDesc. This table is scraped directly from AZ ROC's own classification list.

PrefixScopeExample codes
AGeneral EngineeringA, A-4 Drilling, A-9 Swimming Pools, A-14 Asphalt Paving
BGeneral Residential / CommercialB General Residential, B-1 General Commercial, B-3 General Remodeling
CCommercial SpecialtyC-37 Plumbing, C-39 Air Conditioning and Refrigeration, C-11 Electrical, C-16 Fire Protection Systems, C-42 Roofing, C-78 Solar Plumbing
CRCommercial/Residential Specialty (Dual)CR-37 Plumbing, CR-39 Air Conditioning and Refrigeration, CR-11 Electrical, CR-42 Roofing
KDual (General)KA Dual Engineering, KB-1 Dual Building Contractor, KB-2 Dual Residential and Small Commercial
RResidential SpecialtyR-11 Electrical, R-37 Plumbing (Including Solar), R-39 Air Conditioning and Refrigeration, R-62 Minor Home Improvements

Full code list used by licenseClassification:

Pass any of these codes into licenseClassification to filter results to that endorsement.

License Status Reference

Active statuses — contractor may legally work

StatusMeaning
ActiveLicense in good standing, contractor may bid and build
Active - ProbationActive but subject to Board-imposed conditions
Pending RenewalRenewal application in process

Inactive / restricted statuses — contractor may not legally work

StatusMeaning
SuspendedTemporarily barred from contracting
ExpiredLicense lapsed; renewal not completed
CancelledLicense cancelled (often voluntary)
RevokedPermanently terminated by ROC action

Use licenseStatus: "ACTIVE" to receive only currently authorized contractors.

FAQ

Do I need an AZ ROC account or API key? No. The scraper reads AZ ROC's own public contractor-search backend. There is no public search API — this actor is the alternative.

Why does resultsPerPage have no effect? AZ ROC's search returns every matching record in a single response — the site's own "Next" pagination is purely a client-side display convenience over data it already has in full. This actor reads that same complete response directly, so there's nothing to paginate and no page-size setting to apply.

How reliable is licenseClassification filtering? AZ ROC's own classification search parameter was found (through direct testing) to return additional, unrelated classifications alongside the requested one rather than filtering exactly. To guarantee correct results, this actor always applies an exact match against each license's own parsed classification code after fetching results, rather than trusting AZ ROC's filter alone.

Why is expirationDate the same as renewedThroughDate? AZ ROC's contractor detail page shows a single forward-looking date, labeled "Renewed Through" — there is no separate expiration date exposed. Both fields carry that value for compatibility with schemas that expect an expirationDate field.

Why are some bond/complaint fields null? bondExpirationDate is not exposed by AZ ROC's bond data at all (only an effective date). Complaint and bond details require scrapeDetailPage (and scrapeComplaints for complaints); with both off, or when a license genuinely has no bond or complaint record, those fields are null.

What proxy do I need? AZ ROC's search backend has responded to direct and datacenter requests during testing, but residential is recommended for larger production runs to reduce rate-limiting risk.

Something's not working. Open an issue on the Issues tab with your input and the run link — we respond quickly.

AZ ROC contractor license records are public information, published by the State of Arizona and viewable by any visitor without logging in. Scraping publicly available government records is legal in most jurisdictions, and this actor does not access private data or bypass any login. You are responsible for how you use the data — follow AZ ROC's Terms of Use and applicable data-protection law, and consult a lawyer if you are unsure. See Apify's guide on the legality of web scraping.

Browse all ParseBird actors on Apify Store.