AHPRA Practitioner Scraper
Pricing
from $250.00 / 1,000 registration number lookups
AHPRA Practitioner Scraper
Under maintenanceLook up Australian healthcare practitioners on the AHPRA register by registration number or by name + state + profession. Returns full structured profiles: name, profession, specialty, registration status, conditions, qualifications, principal place of practice. No official AHPRA API exists.
Pricing
from $250.00 / 1,000 registration number lookups
Rating
0.0
(0)
Developer
AHPRA Scraper
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Look up Australian healthcare practitioners on the public AHPRA register. Pass in a registration number and get back a structured profile. Pass in a name and get back a list of matches you can drill into.
There's no official AHPRA API. This actor fills that gap.
What this is for
If you've ever needed to verify whether a doctor, nurse, dentist or other registered health practitioner in Australia is who they say they are, you've used the AHPRA register. The site works fine for one-off lookups. It falls apart the moment you need to do fifty.
This actor is the bulk version. Send a list of registration numbers, get back structured JSON. Send a list of names, get back match lists.
Common reasons people use it:
- Locum and recruiting agencies verifying that a candidate's registration is current, isn't suspended, and doesn't carry conditions before booking a shift.
- Hospitals and clinics running a monthly sweep over their roster to catch lapsed registrations or new conditions before the next audit.
- Insurance underwriters and medico-legal firms doing due diligence on practitioners involved in a claim or complaint.
- International medical councils and migration agents confirming that an Australian-trained practitioner's credentials match what's been declared.
- Compliance officers at large practice groups who need an audit trail for credentialling decisions.
- Journalists and researchers investigating cohorts of practitioners. People have used it to map suspended specialists by state, find every cosmetic surgeon currently working under conditions, and pull longitudinal data for academic work.
If your workflow currently involves someone tabbing through ahpra.gov.au and pasting names into a spreadsheet, this is the upgrade.
What you get back
For each registration number you submit, the actor returns a single record:
| Field | Type | What it is |
|---|---|---|
regno | string | The registration number you supplied |
found | boolean | true if a practitioner was matched, false if not |
fullName | string | Full name including title (e.g. "Dr Jane Citizen") |
profession | string | E.g. "Medical", "Nursing and Midwifery", "Dental" |
specialty | string | null | E.g. "Plastic surgery". Specialists only |
registrationStatus | enum | Registered, Registered (with conditions), Suspended, Cancelled, Not registered, or Unknown |
conditions | string | null | The full free-text of any conditions or undertakings on the practitioner |
reprimands | string | null | Reprimands listed on the public register |
notations | string | null | Notations listed on the public register |
firstRegistered | string | null | First registration in profession, in ISO format (YYYY-MM-DD) |
principalPlaceOfPractice | object | null | { suburb, state, postcode } |
specialistColleges | string[] | List of specialist registrations (specialists only) |
qualifications | string[] | List of qualifications |
cpdCompliant | boolean | null | Always null. CPD status isn't on the public register |
scrapedAt | string | ISO timestamp of when the lookup ran |
sourceUrl | string | The AHPRA public register URL |
For name searches, you get a query record with a results array of summary rows. Each row has regno, fullName, profession, suburb, and state. Set includeFullDetails: true and the actor will follow up each match with a full regno lookup.
How to use it
The actor has two modes. Pick one per run.
Mode 1: by registration number
This is what you'll use 90% of the time. Drop in a list of regnos and get back full profiles.
{"mode": "regno","regnos": ["MED0001234567","NMW0002345678","DEN0003456789"]}
Format is three letters plus ten digits. The letter prefix tells you the board:
| Prefix | Board |
|---|---|
| MED | Medical |
| NMW | Nursing and Midwifery |
| DEN | Dental |
| PHA | Pharmacy |
| PSY | Psychology |
| OPT | Optometry |
| PHY | Physiotherapy |
| POD | Podiatry |
| CMR | Chinese Medicine |
| CHI | Chiropractic |
| OST | Osteopathy |
Bad regnos (wrong format, typos) are skipped with a warning. The run keeps going. You won't lose your batch over one fat-fingered row.
Mode 2: by name
Use this when you have a name but not the regno. Each search takes a name, an optional state, and an optional profession. Narrow it down or you'll get hit with the AHPRA pagination cap (about 10 results per query).
{"mode": "name","searches": [{ "name": "John Smith", "state": "NSW", "profession": "medical" },{ "name": "Sarah Lee", "state": "VIC", "profession": "nursing" }],"includeFullDetails": false}
Valid state values: NSW, VIC, QLD, WA, SA, TAS, ACT, NT.
Valid profession values: medical, nursing, dental, pharmacy, psychology, optometry, physiotherapy, podiatry, chinese, chiro, osteo.
Set includeFullDetails: true if you want the actor to chase up every match with a full profile lookup. You'll be billed an extra event per result so don't tick it for fuzzy queries unless you actually want everything.
Dry run
Pass dryRun: true to validate your input without scraping or being charged. Useful for sanity-checking a 500-row batch before you commit.
{ "mode": "regno", "regnos": ["MED0001234567"], "dryRun": true }
Pricing
Pay-per-event. You're billed only for events that actually produce data.
| Event | Price (USD) | When you're charged |
|---|---|---|
regnoLookup | $0.25 | Per successful regno lookup. Includes the full profile |
nameSearch | $0.05 | Per name-search query. Returns up to 10 matches |
nameSearchResult | $0.25 | Per match when includeFullDetails: true is set |
Failed lookups (regno not found, network error) aren't charged.
A few example costs:
- Verifying a single locum before a shift: $0.25
- Pre-engagement check on a 20-candidate shortlist: $5.00
- Monthly sweep of a 200-practitioner hospital roster: $50.00
- Investigating "all Smiths in NSW Medical" with full details: $0.05 for the search plus $0.25 per match
Why this much? AHPRA verification is a compliance function, not a bulk data product. The data is high stakes (a missed condition or suspension can cost you a credentialling decision, an insurance claim, or a court case). There's no official AHPRA API, so the only alternative is a developer building this in house, which is two to three weeks of work. We've priced this against background-check and KYC providers, not against bulk scrapers.
If you're running thousands of lookups a month, the public rate isn't the right rate for you. Get in touch through the Apify support contact on the actor page and we'll work out a private deal.
Examples
Regno lookup output
{"regno": "MED0001234567","found": true,"fullName": "Dr Jane Citizen","profession": "Medical","specialty": "Plastic surgery","registrationStatus": "Registered","conditions": null,"reprimands": null,"notations": null,"firstRegistered": "2005-03-15","principalPlaceOfPractice": {"suburb": "Sydney","state": "NSW","postcode": "2000"},"specialistColleges": ["Specialist registration in Plastic surgery"],"qualifications": ["MBBS", "FRACS"],"cpdCompliant": null,"scrapedAt": "2026-05-02T12:34:56.789Z","sourceUrl": "https://www.ahpra.gov.au/registration/registers-of-practitioners.aspx"}
A practitioner with conditions on their registration looks like this:
{"regno": "MED0009876543","found": true,"fullName": "Dr John Example","profession": "Medical","specialty": null,"registrationStatus": "Registered (with conditions)","conditions": "The practitioner must not perform cosmetic surgical procedures except in an accredited hospital. The practitioner must complete a Board-approved education programme on professional boundaries within 12 months.","reprimands": null,"notations": null,"firstRegistered": "1998-11-02","principalPlaceOfPractice": { "suburb": "Melbourne", "state": "VIC", "postcode": "3000" },"specialistColleges": [],"qualifications": ["MBBS"],"cpdCompliant": null,"scrapedAt": "2026-05-02T12:34:56.789Z","sourceUrl": "https://www.ahpra.gov.au/registration/registers-of-practitioners.aspx"}
Name search output
{"query": { "name": "Smith", "state": "NSW", "profession": "medical" },"resultCount": 2,"results": [{"regno": "MED0001111111","fullName": "Dr Alice Smith","profession": "Medical","suburb": "Sydney","state": "NSW"},{"regno": "MED0002222222","fullName": "Dr Bob Smith","profession": "Medical","suburb": "Newcastle","state": "NSW"}],"scrapedAt": "2026-05-02T12:34:56.789Z"}
Calling the actor from your code
You don't have to use the Apify console. Most people who run this in production call it from their own backend.
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("emblematic_easel/ahpra-practitioner-scraper").call(run_input={"mode": "regno","regnos": ["MED0001234567", "NMW0002345678"],})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["regno"], item["fullName"], item["registrationStatus"])
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('emblematic_easel/ahpra-practitioner-scraper').call({mode: 'regno',regnos: ['MED0001234567', 'NMW0002345678'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const item of items) {console.log(item.regno, item.fullName, item.registrationStatus);}
Webhooks
Set up an Apify webhook on the actor and point it at your endpoint. You'll get a POST every time a run finishes, with the dataset ID. Pull the records and process them on your end.
Patterns people actually use
Daily roster sweep
You've got 200 practitioners on staff. You want to know within 24 hours if any of them get suspended, cancelled, or have new conditions added.
Run the actor once a day with mode: "regno" and your full list. Diff the results against yesterday's snapshot in your own database. Flag any change to registrationStatus or conditions for review.
Pre-engagement check
A locum signs up. Before you offer them a shift, run their regno through the actor. If registrationStatus is anything other than Registered, or if conditions is non-null, it goes to the credentialling team before the booking is confirmed.
Cohort investigation
You suspect a pattern. Run a mode: "name" search across a list of names or surnames, set includeFullDetails: true, and then filter the dataset for the field you care about (usually conditions or registrationStatus).
Compliance and terms of use
The AHPRA register is a public register required by the Health Practitioner Regulation National Law (Section 222). The data this actor returns is public information that anyone can read on ahpra.gov.au.
You're responsible for how you use the data. Australian privacy law applies, especially if you're combining it with other personal information. AHPRA's website terms of use also apply.
The actor returns data exactly as published on the public register on the day of the lookup. It doesn't enrich, infer, or correct.
If you're using this for a credentialling or claims decision, always corroborate against the live AHPRA website before you act. Registers change daily.
How it works (briefly)
The AHPRA register isn't a friendly site to scrape. The form requires a two-stage POST with cookies, ASP.NET ViewState, and EventValidation tokens that you have to round-trip in the right order. Get any of it wrong and you get a generic error page.
This actor calls a private Cloudflare Worker that handles all of that. The Worker is rate-limited and IP-stable. The actor is the public, billable wrapper around it.
If AHPRA changes their HTML, the Worker gets fixed once and every customer benefits. You don't have to update anything on your end.
Limitations
There are a few things you should know up front:
- CPD compliance isn't on the public register. The actor always returns
cpdCompliant: null. If you need CPD status, you have to ask the practitioner directly. - Specialist colleges only show up for practitioners who've completed specialist training and registered for it. A GP won't have specialist registration listed.
- Name searches return up to ten results. That's an AHPRA pagination limit. Narrow the query with
stateandprofessionif you're getting cut off. - Common names with no filter ("Smith" with no state, no profession) won't return everyone. Use the registration number whenever you can.
- The actor doesn't store data. Everything goes to your Apify dataset. If you want a long-term record, copy it to your own storage.
- Rate limits exist. Don't try to run a million regnos in one batch. The Worker will throttle you, and so will AHPRA. Batches of a few thousand at a time work fine.
FAQ
Is this actually compliant with AHPRA's terms?
The register is public by law. Reproducing public data for legitimate purposes (verification, compliance, credentialling, journalism) is generally fine. Reselling raw extracts as a database product is a different question and you should get your own legal advice. The actor doesn't change the legal status of the data.
Why isn't this just an API on the AHPRA website?
Ask AHPRA. They've been asked, repeatedly, for years.
Can I run this on a free Apify plan?
Yes. You'll get a small monthly credit you can use to test. Bigger batches need a paid Apify plan or a top-up.
What happens if AHPRA's website goes down?
The actor will return errors for the affected lookups. You won't be charged for them. AHPRA's downtime is usually short (a few minutes, sometimes an hour during scheduled maintenance).
Can you add field X (e.g. CPD, employer history, complaint history)?
Probably not. The actor returns what's on the public register. If AHPRA doesn't publish a field, the actor can't return it. Complaint history in particular is confidential under the National Law unless it's resulted in a public reprimand or condition.
I run a clinic group with thousands of practitioners. Can you do bulk pricing?
Yes. Use the Apify support contact on the actor page and mention rough monthly volume. Bulk deals come down a fair bit from the public rate.
Versioning
This is version 0.1. The output schema is stable but new optional fields may appear in future versions. Existing fields won't be removed without a major version bump.
Support
Questions, bug reports, or field requests go through the Apify support channel on the actor page. Include a sample input and the run ID if you're reporting a bug.