← Guides

How-to

How to run Washington Contractor License Lookup & Verify (L&I)

Step-by-step: the exact input, what each field does, and the rows that come back from WA L&I (Socrata).

You have a Washington contractor in front of you — a sub about to start work, a vendor being onboarded, a name on an insurance file — and you need the state’s record of them: are they registered with L&I, is the registration active, and when does it expire. Washington gives you a Verify a Contractor page that answers exactly that, one contractor at a time, as a web page. For one sub that’s a two-minute job and you should just use it. It stops being reasonable when the question becomes a list: fifty subs re-checked each quarter is two hundred searches a year, each one typed in by hand and copy-pasted into a spreadsheet, and the portal has no export to skip that step. This actor asks the same question and hands back rows instead of pages.

What you’ll need

Nothing but an Apify account. The actor talks to WA L&I (Socrata) directly.

No API key, no proxy, no CAPTCHA credits. Washington publishes its contractor registrations as an official Socrata open-data dataset on data.wa.gov — public JSON, documented, free to query. This is the easiest tier of target there is, and it’s worth being blunt about what that means: nothing here is being worked around, and you are not paying for access. If you can write a SoQL query, you can pull the same data yourself and pay nobody. What this actor gives you is the normalised schema, the two-way search, the cost cap, and the nightly check that the columns still mean what they meant yesterday.

Step 1 — Open the actor

Open Washington Contractor License Lookup & Verify (L&I) on the Apify Store and press Try for free. The actor’s own page on this site lists its live health and pricing.

The Washington Contractor License Lookup & Verify (L&I) listing on the Apify Store
The listing on the Apify Store. Pricing and the nightly health record are both public.

Step 2 — Fill in the input

The input form for Washington Contractor License Lookup & Verify (L&I) in the Apify Console
The input form, as it appears in the Apify Console.
FieldTypeRequiredWhat it does
querystringyesA Washington L&I license number or business name. Searches by exact license number and by business-name substring; principal names are returned on the row but are not searchable.
maxResultsintegernoCap on matches returned (bounds cost). This is now honoured end to end - the Socrata query is issued for this many rows. (default 50)

query is the field people get wrong, because it does two jobs at once. Every run searches L&I twice: once for an exact match on the registration number (contractorlicensenumber), and once for a substring match against the business name (businessname). So a full registration number is a verify — one contractor, one row. A word is a search: construction matches thousands of registered businesses, pacific roof matches a handful. Start narrow and widen, rather than the other way round.

The substring half runs against the business name only. A principal’s name comes back on the row (person_name, from L&I’s primary-principal field), but it is not a separate index you can query — so a sole proprietor registered under their own name will turn up, while an owner behind a company name will not. A missing match is not proof someone is unregistered; it may just be a DBA you don’t know about.

maxResults (default 50) is the only thing standing between a broad name fragment and a bill, since you’re charged per row returned. Set it deliberately on any search you haven’t run before.

A working input:

{
  "query": "construction",
  "maxResults": 25
}

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.

A healthy run is dull and fast. There’s no browser and no login — the whole thing is two filtered Socrata requests (the exact-number search, then the name search), each requested at your maxResults, deduplicated on registration number and cut to it. Because the dataset already carries status, dates, address, phone and principal, there is no second fetch per contractor: a lookup is one request and a verify finishes in seconds. Expect a single row from a registration number and anywhere from a handful to your maxResults ceiling from a name.

Empty usually means the query, not the actor. Registration numbers have to match exactly, and names have to match the way L&I spelled them — punctuation, & versus and, the LLC suffix. Cut the name back to its shortest distinctive fragment and run it again before you conclude anyone is unregistered.

Step 4 — Read the output

Each run returns a labelled table, not raw JSON:

The output fields returned by Washington Contractor License Lookup & Verify (L&I)
The output view — every field the actor returns, named and typed.

Every row looks like this — a real row from a real run:

{
  "state": "WA",
  "license_number": "ECOSTSC758NN",
  "business_name": "!ECO STAR C G CONSTRUCTION LLC",
  "person_name": "GUERRERO MARTINEZ, CARLOS I.",
  "license_type": "CONSTRUCTION CONTRACTOR",
  "status": "ACTIVE",
  "issue_date": "2025-08-15T00:00:00.000",
  "expiration_date": "2027-08-15T00:00:00.000",
  "city": "VANCOUVER",
  "address": "2420 COLUMBIA HOUSE BLVD #311",
  "zip_code": "98661",
  "phone": "5039573452",
  "matched_by": "business_name",
  "source_url": "https://secure.lni.wa.gov/verify/"
}
FieldExample valueMeaning
stateWAAlways ‘WA’ for this actor
license_numberECOSTSC758NNL&I contractor registration / license number
business_name!ECO STAR C G CONSTRUCTION LLCLicensed business name
person_nameGUERRERO MARTINEZ, CARLOS I.Primary principal / owner name
license_typeCONSTRUCTION CONTRACTORL&I license type (e.g. Construction Contractor)
statusACTIVELicense status (e.g. ACTIVE, EXPIRED, RE-LICENSED)
issue_date2025-08-15T00:00:00.000License effective date
expiration_date2027-08-15T00:00:00.000License expiration date

Two fields are why anyone runs this: status and expiration_date.

Read them knowing what a Washington registration actually is. L&I doesn’t test contractors the way some states license them — it registers them, and registration is conditional on having a surety bond and general-liability insurance on file with the state. That’s the whole point of the check: an ACTIVE registration means L&I currently holds a bond and an insurance policy for that contractor, and a lapse in either is what pushes the record out of ACTIVE. So status is a proxy for “bonded and insured today”, and expiration_date is the date that assurance runs out — the one to sort by when you’re deciding whether a sub goes out of date halfway through your project.

Be precise about the limit here. The bond amount, the surety, the insurer and the workers’-comp account live in separate L&I datasets and are not joined in this version — those fields come back null, not guessed. This dataset tells you the registration is in effect; it does not tell you the bond is $12,000 from a named surety. If you need the bond and insurance rows themselves, L&I’s own Verify page (linked on every row as source_url) is where you go.

The rest is straightforward, with two things to watch. person_name is L&I’s primary principal, which is how you tell two similarly-named outfits apart — it is not a full owner list. matched_by tells you why a row is in your results: license_number for an exact hit, business_name for a name that merely contained your search string. Check it before you treat a hit as the contractor. phone arrives as raw digits (5039573452), unformatted, and is null where L&I doesn’t publish one.

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 matched licence — 100 verified records is $0.40, 1,000 is $4.00. You’re charged per row returned, so a search that finds nothing is free, and a single-registration verify costs less than a cent. Apify’s platform compute is billed separately on your plan, and it’s small here: no browser, two HTTP calls. There is no third-party cost inside the run at all, because the source is a free public API. The spend control you actually use is maxResults — a wide name search is the only way to run up a bill on this one.

Where the data comes from

This reads WA L&I (Socrata) directly. The target is Socrata SODA JSON API (data.wa.gov, L&I contractor registrations) - filtered server-side with SoQL. Every night a canary runs this actor against that live source and diffs the result against a frozen fixture — what “verified” means.

This is the front door, not a side entrance. Washington publishes its contractor-registration registry deliberately, as open data, with a documented free API and no anti-bot wall — and that’s the honest frame for the whole actor. What’s fiddly is not getting in; it’s the shape of what’s inside. The columns are the state’s own (contractorlicensenumber, contractorlicensetypecodedesc, primaryprincipalname), the search semantics are yours to build, and the feed is an open-data snapshot that L&I refreshes on business days — so it can lag the board’s live screen, and for a formal compliance decision you confirm against L&I itself. The thing worth paying for is that the schema stays stable for you, and that when Washington renames a column or changes a status value, the nightly canary notices instead of your pipeline.

See it used

Search Washington Contractors by Business Name resolves a business name to its L&I registration records.

Last updated 2026-07-13