Verify a Vermont Professional License
Purpose
Look up and verify a professional license issued by the Vermont Office of Professional Regulation (OPR) on the public "Find a Professional" guest portal, and return the license-holder's identity, profession/license type, current status (Active / Expired / Lapsed / etc.), and key dates. Read-only — this skill only searches and reads the public license record; it never edits, applies, renews, or pays.
When to Use
- A user gives you a Vermont license number (format
NNN.NNNNNNN, e.g.075.0045018) and asks for the license status, the licensee's name, profession, or expiration date. - You need to confirm whether a Vermont-licensed professional (nurse, nursing assistant, cosmetologist, real-estate agent, and the many other OPR-regulated professions) holds a current, active license.
- You need the issue/effective/expiration dates or the licensee's city/town for a Vermont OPR license.
- Not for Vermont Board of Medical Practice physicians (those live on healthvermont.org) and not for disciplinary/complaint history (a separate "Complaints, Conduct & Discipline" page).
Workflow
This is a server-rendered Pega Platform guest portal ("NGLP") fronted by Imperva /
Incapsula anti-bot. There is no usable public API — the only path is the browser UI, and
the session is gated by per-request Pega tokens. Drive it with a stealth browser session
(--verified --proxies).
- Start a stealth session and navigate to the entry point:
https://secure.professionals.vermont.gov/prweb/app/default/The server mints a per-session token into the URL (/app/default/<TOKEN>*/!STANDARD). The token is single-use — always enter via/prweb/app/default/; never reuse a tokenized URL. Wait ~3s for the Pega harness to render client-side. - Open the lookup: snapshot the page and click "FIND A PROFESSIONAL". This loads the licensee-lookup form (the "LICENSEE LOOKUP" tab is active by default).
- Enter the license number — with REAL keystrokes. Click the License Number field
(placeholder
123.1234567), then type the full value075.0045018character-by-character (browse type, notbrowse fill). See Gotcha #1 — this is the single most important step. Leave First/Last/Business Name blank and leave Profession on "SELECT PROFESSION". - Commit the value: press Tab. This blurs the field, firing Pega's onchange AJAX
(
...eventSrcSection=...NGLPLicenseLookupInput), which writes the value into Pega's clipboard and enables the DISPLAY RESULTS button. - Submit: wait ~2s, re-snapshot, then click DISPLAY RESULTS. Wait ~3s (a "Please wait" progress bar shows during the lookup).
- Verify the search actually used your value: read the body text and confirm the header says "Displaying 1 results for 075.0045018" (the license number must appear after "for"). A results grid shows License #, Profession Type, Status, First/Last Name, City.
- (Optional) Open full detail: click the row's DETAILS button to open a modal with the licensee's address, profession, first-issuance/effective/expiration dates, and case history.
- Extract the fields into the JSON shape in Expected Output.
Site-Specific Gotchas
- Type, never fill. Pega's text-input control copies the field into its server-side
clipboard only on real keyboard
input+blur events.browse fill(which sets.valuedirectly) makes the value visible and even enables the button, but Pega searches an empty string — you get "Displaying 0 results for " (note the blank after "for"). Usebrowse click <field>→browse type 075.0045018→browse press Tab. Confirmed: in early iterationsfill+Tab returned 0 results; switching totype+Tab returned the record. - DISPLAY RESULTS starts disabled. Its enable expression is
disableWhen = this['.LicenseLookupVal']!='true'; the flag flips only after a field's onchange (the Tab blur) commits a value. Visual "enabled" appearance is not proof — always verify via the "Displaying N results for <number>" header that the value was actually searched. - License number format is exact:
NNN.NNNNNNN(3 digits, a dot, 7 digits — the placeholder is123.1234567). The leading segment is a profession/board code (e.g.075= Licensed Nursing Assistant). Type the full value in the single License Number field; do not split it. - Imperva blocks are intermittent and proxy-IP-reputation based. The same
--verified --proxiesconfig that succeeds on one session can return an Imperva interstitial ("Access denied — Error 15 — This request was blocked by our security service", with your IP / Proxy IP / Incident ID) on the next. If you hit it: rotate to a fresh session (new proxy IP) and retry. Attaching automation via a pre-created keep-alive session + CDP connect URL was more reliable than a plain remote-open in testing. Never run without stealth. - Refs ([X-Y]) are unstable. Every Pega AJAX round-trip (field commit, search, detail open)
re-renders the harness and renumbers accessibility refs. Re-
snapshotbefore every click; never reuse a ref captured before an AJAX call. - No public API. All
/prweb/PRServletCustom/...endpoints require a live Pega session +pzTransactionId/AJAXTrackIDtokens issued during the harness boot; they are not independently callable. Don't waste time looking for a JSON lookup endpoint — drive the UI. - Scope caveats shown on the form: "Not all discipline is linked to the licensee lookup results" — disciplinary history lives on a separate Complaints/Conduct & Discipline page.
- Other entry points exist (
PROFESSION ROSTER DOWNLOADtab; name-based search via First/Last/Business Name fields) but the license-number lookup is the most precise.
Expected Output
Successful single-record match (the canonical case — example license 075.0045018):
{
"success": true,
"license_number": "075.0045018",
"licensee_name": "Adam Johnson",
"license_type": "Licensed Nursing Assistant",
"status": "Expired",
"issue_date": "April 01, 2009",
"effective_date": "April 01, 2009",
"expiration_date": "November 30, 2010",
"additional_fields": {
"profession": "Nursing",
"first_name": "Adam",
"last_name": "Johnson",
"address_line_1": "CSC - Box A026",
"city": "Castleton",
"state": "Vermont",
"country": "United States",
"zip_code": "05735",
"case_history": "No cases"
},
"error_reasoning": null
}
No record found (valid format, but the search header reads "Displaying 0 results for <number>"):
{
"success": false,
"license_number": "099.9999999",
"error_reasoning": "Displaying 0 results for 099.9999999 — no matching license on file."
}
Blocked by anti-bot (Imperva interstitial before the form/results render):
{
"success": false,
"license_number": "075.0045018",
"error_reasoning": "Imperva 'Access denied / Error 15' interstitial — request blocked by security service (proxy IP reputation). Retry with a fresh stealth session / rotated proxy IP."
}