RateMDs Scraper [From $1.5💰] | Profiles | Reviews | Leads
Pricing
from $1.40 / 1,000 doctors
RateMDs Scraper [From $1.5💰] | Profiles | Reviews | Leads
Extract doctor profiles and patient reviews from RateMDs for reputation monitoring, healthcare lead generation and patient sentiment analysis. US & Canada data, structured JSON on Apify.
Pricing
from $1.40 / 1,000 doctors
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
RateMDs Scraper
A RateMDs scraper that extracts doctor profiles and patient reviews from RateMDs.com across the United States and Canada: 33 profile fields land in the default dataset and 15 review fields in a separate reviews dataset — built for reputation monitoring for doctors and healthcare review monitoring when no official RateMDs API exists.
Main use cases
- Doctor reputation monitoring / online reputation management for doctors — track the five rating dimensions plus fresh patient reviews for a physician watchlist on a schedule.
- Healthcare review monitoring — pull RateMDs reviews alongside the other physician rating websites (Healthgrades, Vitals, Zocdoc, WebMD) in a multi-site pipeline.
- Patient sentiment analysis — analyze review text, star ratings and per-dimension sub-ratings to see how patients talk about a practice.
- Healthcare lead generation — build doctor leads with ratings and reviews: profile rows carry phone, address, specialty, review count and average score.
- Physician market research — scrape doctor reviews for a research dataset, or compare reviews across cities and specialties.
- Find the best rated doctors in any US or Canadian city — search by state/city and specialty to surface top-rated physicians.
How it works
The actor runs a CheerioCrawler (no browser automation) with Apify residential proxies. In search mode it walks paginated listing pages (/best-doctors/{state}/{city}/[{specialty}]/?page={N}); in profile mode it fetches specific /doctor-ratings/{slug}/ profile URLs directly. It solves the site's HTTP 202 JavaScript proof-of-work challenge inside the request session, then reads structured data from server-rendered window.DATA JSON blobs, JSON-LD (Physician / MedicalWebPage / BreadcrumbList) and DOM fallbacks. Profiles land in the default dataset; reviews go to their own reviews dataset, fetched page by page from the server-rendered organic and partner review pages inside the profile's sticky-IP session.
Does RateMDs Have An API? (And How To Get Its Reviews)
RateMDs publishes no public API — there is no developer portal or documented endpoint for doctor or review data. That gap is why this actor exists: a RateMDs Reviews API substitute that returns the same data as structured JSON.
- No official API: RateMDs exposes no documented REST endpoint, so programmatic access requires a scraper.
- Programmatic reviews: start a run, then read the
reviewsdataset (15 fields per review) withGET /v2/datasets/<reviewsDatasetId>/items, or read both dataset URLs fromGET /v2/actor-runs/:runIdinoutput.profiles/output.reviews. - API-friendly output: an actor output schema (
actorOutputSchemaVersion1) publishes both dataset URLs, so downstream code fetches profiles and reviews without guessing storage IDs.
Scrape RateMDs Doctor Profiles And Patient Reviews
- Two modes:
searchcrawls listing pages by location and specialty;profilescrapes specific doctor profile URLs directly. - Dual-dataset writes: 33 profile fields (name, specialty, practice, address, phone, education, languages, geo-coordinates, five rating dimensions) to the default dataset; 15 review fields (text, date, stars, sub-ratings, author, appointment type, source) to the separate
reviewsdataset — each with its own schema and Output-tab view. - Parallel by default:
maxConcurrency(default 10, max 20) fills every slot immediately; those slots share up to 3 sticky residential sessions, so the proof-of-work challenge is solved once per session, not once per request. - Review pagination handled: both organic (
?page=N) and partner (?third_party_page=N) lists are walked — up to 10 pages per list per doctor, and pages after page 1 are prefetched in small parallel batches so doctors with hundreds of reviews no longer cost one round-trip per page.
Monitor Physician Reviews Across RateMDs, Healthgrades, Vitals And Zocdoc
Reputation-monitoring platforms list RateMDs as a monitored source alongside Healthgrades, Vitals, WebMD, Yelp and Zocdoc, so healthcare review monitoring needs the RateMDs slice too:
- Run daily or weekly per doctor or per city/specialty to catch new reviews.
- Every review row carries
runId,dateandsource(organic/partner), so you can diff runs over time. - Profile rows carry
reviewCount,averageScoreand the five sub-ratings — a rating trend line per physician. - Reviews are stored page by page as they arrive, so a stopped run keeps every page it already fetched.
Build A Doctor Lead List With Ratings And Reviews
The profile dataset doubles as a doctor lead list for healthcare lead generation and provider data enrichment: contact and geo fields (phone, streetAddress, city, state, zipCode, country, latitude, longitude), credential context (name, specialty, practiceName, school, graduationYear, languages, openingHours, clinics), the ratings that qualify a lead (reviewCount, averageScore, overallRating, staffRating, punctualityRating, helpfulnessRating, knowledgeRating) and enrichment links (profileUrl, photoUrl). With search mode filtering by state/city and specialty, you can build geographically targeted physician lists for the US and Canada.
Patient Sentiment Analysis From Real Doctor Reviews
The dedicated reviews dataset is built for patient sentiment analysis and physician ratings data work:
- Text:
textholds the full review text (description plus title when present). - Ratings:
rating(1-5 overall) plusstaffRating,punctualityRating,helpfulnessRating,knowledgeRatingsub-ratings per review. - Context:
date,author,appointmentType(e.g. "Office visit") andsource(organic= on RateMDs,partner= collected by a partner). - Joins:
doctorName,doctorProfileUrlandrunIdlink every review back to its profile row and run.
Because reviews live in their own dataset rather than embedded in profile items, you can aggregate thousands of reviews without re-parsing profile JSON.
Provider Data Enrichment For US And Canadian Doctors
Coverage is US + Canada only, enforced by the country enum (us / ca / both, default both). The 33 profile fields cover identity (name, gender, profileUrl), credentials (specialty, school, graduationYear), location, contact and practice, reputation (reviewCount, averageScore, overallRating, staffRating, punctualityRating, helpfulnessRating, knowledgeRating) and media/meta (photoUrl, breadcrumbTrail, scrapedAt).
location accepts state/city paths (tx/houston, on/toronto), country prefixes (us/, ca/) or full RateMDs URLs — cleaned up automatically.
Find The Best Rated Doctors In Any US Or Canadian City
RateMDs' own city ranking pages (e.g. "Best Doctors in Toronto, ON") prove the best-rated-doctors-in-city query pattern across US and Canadian cities. This actor answers it with search mode:
locationtakes a state or state/city slug (tx,tx/houston,on,on/toronto);specialtynarrows to a slug (dentist,family-gp,dermatologist,cardiologist).maxPagescaps listing pages per location/specialty combination (0 = unlimited, default 10), following<link rel="next">;maxItemscaps total profiles (0 = unlimited, default 100).
Input Parameters
All 11 input fields from input_schema.json. Only mode is required.
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
mode | search | profile | Yes | search | search crawls listing pages by location/specialty; profile scrapes specific doctor profile URLs. |
location | string | No (search mode) | "" | State/city path from the RateMDs URL, e.g. tx/houston, on/toronto. Country prefixes (us/, ca/) and full RateMDs URLs accepted. Missing value in search mode fails fast. |
specialty | string | No | "" | Specialty slug from the RateMDs URL path, e.g. dentist, family-gp, dermatologist. Used in search mode. |
country | us | ca | both | No | both | Country to search: us, ca or both. |
profileUrls | string[] | No (profile mode) | [] | Doctor profile URLs or slugs to scrape directly. |
maxItems | integer | No | 100 | Max doctor profiles. 0 = unlimited (capped by Apify limits). |
maxPages | integer | No | 10 | Max listing pages per location/specialty. 0 = unlimited. |
includeReviews | boolean | No | true | Scrape patient reviews into the separate reviews dataset. Increases scraping time significantly. |
maxReviewsPerDoctor | integer | No | 5 | Max reviews per doctor. 0 = all; organic + partner lists, up to 10 pages per list per doctor. |
maxConcurrency | integer | No | 10 | Parallel requests, range 1-20. Up to 3 sticky residential sessions are shared by those requests, so PoW is solved once per session. 10+ slots need 1024 MB+ memory. |
proxy | object | Yes* | residential prefill | Residential proxies REQUIRED — datacenter IPs get HTTP 406. Prefill: {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}. |
* Apify Proxy with the RESIDENTIAL group is mandatory; the actor fails with an explicit message if RateMDs returns 406. |
Output Fields
The run's Output tab shows both outputs side by side — Doctor profiles and Patient reviews — each linking to its own dataset. GET /v2/actor-runs/:runId returns the same links in output.profiles / output.reviews.
Doctor profiles — default dataset, schema profiles_dataset_schema.json (33 fields)
One item per doctor; reviews are not embedded — they live in their own dataset. The default dataset declares its schema in .actor/actor.json (storages.datasets.default), so the Output tab renders a Doctors table and the field list is published to MCP/AI agents.
- Identity:
name,profileUrl,gender,specialty,photoUrl,breadcrumbTrail - Credentials:
school,graduationYear - Address:
streetAddress,city,state,stateSlug,country,zipCode,latitude,longitude - Contact and practice:
phone,practiceName,clinics,openingHours,languages - Ratings:
reviewCount(headline = organic + partner),averageScore,overallRating,staffRating,punctualityRating,helpfulnessRating,knowledgeRating - Meta:
scrapedAt - Fallback-only (only when a review falls back into the default dataset):
type(always"review"; profiles carry notype),runId,doctorName,doctorProfileUrl
Patient reviews — separate reviews dataset, schema reviews_dataset_schema.json (15 fields)
When includeReviews is true, every scraped review is written to its own dataset, declared under storages.datasets.reviews. The two storages are completely separate: the default dataset holds one item per doctor (Output-tab view Doctors), the reviews dataset one item per review (view Reviews).
- Core:
id(RateMDs rating id, de-duplicates reviews across paginated fetches),date(YYYY-MM-DD),rating(1-5),text(full review text: description plus title when present) - Sub-ratings:
staffRating,punctualityRating,helpfulnessRating,knowledgeRating - Context:
author,appointmentType,source(organic= written on RateMDs,partner= collected by a partner) - Joins and meta:
type(always"review"),doctorName,doctorProfileUrl,runId
Each review links to its doctor via doctorName / doctorProfileUrl; runId isolates items of a single run. On the platform the reviews alias is a run-scoped storage created at run start (fresh for every run), logged as reviewsDatasetId. Fetch it from the run page (Storage tab -> Dataset -> reviews) or with GET /v2/datasets/<reviewsDatasetId>/items.
Fallback: a restricted-token run (LIMITED_PERMISSIONS, e.g. MCP/token runs) that cannot write the second storage logs a warning and writes those reviews into the default dataset marked "type": "review". Start from the Apify Console (full access) for the separate dataset.
Example Input And Output
Example Input — search mode, Toronto dentists
{"mode": "search","location": "on/toronto","specialty": "dentist","country": "ca","maxItems": 50,"maxPages": 5,"includeReviews": true,"maxReviewsPerDoctor": 20,"proxy": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Example Output — profile row (default dataset)
{"name": "Dr. Jane Doe","profileUrl": "https://www.ratemds.com/doctor-ratings/dr-jane-doe-toronto-on/","specialty": "Family Medicine","practiceName": "Toronto Family Clinic","city": "Toronto","state": "Ontario","country": "Canada","phone": "(416) 555-0123","reviewCount": 42,"averageScore": 4.6,"overallRating": 4.6,"staffRating": 4.5,"punctualityRating": 4.7,"helpfulnessRating": 4.6,"knowledgeRating": 4.8,"latitude": 43.6532,"longitude": -79.3832,"scrapedAt": "2026-10-05T12:34:56.789Z"}
Example Output — review row (reviews dataset)
{"id": 9003,"date": "2024-01-15","rating": 5,"text": "Excellent doctor, very caring...","staffRating": 5,"punctualityRating": 5,"helpfulnessRating": 5,"knowledgeRating": 5,"source": "organic","type": "review","doctorName": "Dr. Jane Doe","doctorProfileUrl": "https://www.ratemds.com/doctor-ratings/dr-jane-doe-toronto-on/","runId": "AbCdEf123456"}
RateMDs Scraper For Apify — Pricing, Performance And Cost
- Pay-per-event pricing:
Doctor$0.0015 per profile (DIAMOND $0.0014),Review$0.00015 per review (DIAMOND $0.00014),Actor Start$0.00005. At the user's maximum charge (ACTOR_MAX_TOTAL_CHARGE_USD) the crawler stops instead of billing more. - Free/paid tier: free-tier accounts get 10 profiles per run; paid accounts are unlimited.
- Memory: 1024 MB default (peak ~330 MB with 6 parallel requests; 256 MB was OOM-killed); 256-4096 MB range, default timeout 3600 s (max 14400 s). Each additional parallel slot parses its own page, so use 1024 MB for 10 slots and 2048 MB for 20.
- Speed: ~100 profiles in 30-60 seconds with 10 parallel requests (was ~2 minutes with a single request). Slots start together and share a few sessions, so the crawler is not limited by one PoW solve per IP. Review pages after page 1 are fetched in parallel (3 at a time), which mainly speeds up
maxReviewsPerDoctorvalues above 20. - Compute: ~0.01-0.05 CU per 100 profiles; CheerioCrawler is 10-20x faster and 4-8x cheaper on Apify compute units than browser automation. Residential bandwidth is required (included in Apify paid plans).
Limitations: residential proxy is an additional cost; free tier limited to 10 profiles per run; partner reviews keep only the fields both lists share (id, date, rating, text, author) — per-item sub-ratings have no organic counterpart and are not guessed; some profile fields may be missing if not present in embedded JSON or JSON-LD.
Anti-Bot Strategy: Residential Proxies And Proof-Of-Work
RateMDs sits behind Cloudflare with a JavaScript proof-of-work challenge, answered without a browser:
- HTTP 202 proof-of-work: page requests get HTTP 202 plus
window.POW_CHALLENGE_DATA = { challenge_nonce, challenge_hmac, difficulty, difficulty_char, issued_at, ... }. The actor solves it like the site's script (SHA-256 overnonce + issued_at + nuntil the hash starts withdifficulty_charrepeateddifficultytimes — difficulty 3 is a few thousand hashes), stores thepow_bypasscookie and refetches in the same session withcontext.sendRequest. - In-session refetch is essential: a solve is only accepted from the sticky proxy IP it was issued to; retrying through Crawlee's queue picks a new IP with a fresh challenge — the failure that previously ended runs with "0 succeeded, 1 failed".
- HTTP 406 handling: datacenter IPs are rejected outright, so
RESIDENTIALis mandatory. A mid-run 406 usually means the sticky IP went bad: the actor retires the session (Apify hands out a different sticky residential IP), drops the cookie for a fresh challenge and retries; the run aborts after 10 blocked responses. Review pages recover the same way, up to 3 rotations per doctor. - Shared sticky sessions:
maxConcurrencyfills every crawler slot immediately, but at most 3 sticky residential sessions are live (MAX_PROXY_SESSIONS). The first request on a session solves the PoW challenge and the rest reuse its cookie, so solve cost scales with sessions rather than slots. Solves are serialized per session (withSessionLock), so concurrent requests cannot interleavepow_trace/pow_bypasscookie writes.
Data extraction priority: (1) window.DATA.* JSON blobs (doctorDetailProps, ratingsPage) — ratings, reviews, schools, languages, locations, coordinates; (2) JSON-LD (Physician / MedicalWebPage / BreadcrumbList) — address, phone, hours, aggregate rating; (3) DOM — listing cards (.doctor-profile-card) and fallbacks.
Endpoints And Review Pagination
- Listing pages:
https://www.ratemds.com/best-doctors/{state}/{city}/[{specialty-slug}]/?page={N}. Pagination follows<link rel="next">up tomaxPages. There is no country prefix —us/andca/prefixes in the input are stripped automatically. - Profile pages:
https://www.ratemds.com/doctor-ratings/{slug}/(also accepts the legacy form/doctor-ratings/{id}/Dr-Name-City-ST.html/). - Review pages (organic):
https://www.ratemds.com/doctor-ratings/{slug}/?page=N(page 1 is the profile URL itself). The response is an ordinary server-rendered HTML page whosewindow.DATA.doctorDetailProps.ratingsPagecontains that page of the list, so it is parsed with Cheerio. The scraper walks it when the organic count exceeds what the profile embedded, from page 1, deduplicating by id. The embedded widget'stotal_pagescan be wrong (1 page even for a doctor with 525 reviews), so page 1's payload is used to correct it. - Review pages (partner):
https://www.ratemds.com/doctor-ratings/{slug}/?third_party_page=N. RateMDs splits reviews into two lists; the headlinereviewCountis the sum, so doctors with hundreds of ratings and 0-2 organic ones (e.g. 426 partner) would otherwise yield none. The same HTML page embedsdoctorDetailProps.thirdPartyRatingsPage; entries use different field names (description,reviewer_name,date_added) and are taggedsource: "partner". - The internal
?json=trueXHR endpoints used by the site's own JavaScript are not called (they are the most aggressively rate-limited part of the site). Both review lists are fetched as plain HTML inside the profile request's session (same sticky IP and solved cookie), up to 10 pages per list per doctor (10 reviews per page).
Integrations & Automation
- Apify Console: paste an input JSON (see Example Input), select the
RESIDENTIALproxy group, start. Both datasets appear on the run's Output tab. - Apify API: start runs with
POST https://api.apify.com/v2/acts/LUulX2IdYvMb9dy3V/runs, pollGET /v2/actor-runs/<runId>, then fetchoutput.profilesandoutput.reviews. - Webhooks: fire on run
SUCCEEDEDto pushoutput.reviewsinto your database or review-monitoring pipeline automatically. - Zapier / Make: trigger on a new run or dataset item to route reviews into Sheets, Airflow or a CRM.
- Recommended schedule: run daily or weekly per doctor watchlist (profile mode) or per city/specialty (search mode) for ongoing healthcare review monitoring.
Related Actors
FAQ
Is there an official RateMDs API?
No. RateMDs publishes no public API — no developer portal, no documented endpoint for doctor or review data. To get RateMDs reviews programmatically you need a scraper like this actor, then query its datasets over the Apify API.
What are the alternatives to this actor?
Other RateMDs-focused actors exist in the Apify Store — parseforge's and scrapersdelight's ratemds-scraper, among them. For adjacent physician rating websites, see the Healthgrades, Vitals and Zocdoc scrapers linked in Related Actors; WebMD scrapers are also available in the Store.
Which websites should I monitor for physician reviews?
Reputation-audit guides typically name Healthgrades, Vitals, RateMDs, WebMD, Yelp and Zocdoc as the core physician review platforms. This actor covers the RateMDs slice; pair it with scrapers for the others.
What are the best doctor rating sites?
Commonly compared sites include Healthgrades, Zocdoc, Vitals and RateMDs. RateMDs covers US and Canadian doctors with multi-dimensional ratings (overall, staff, punctuality, helpfulness, knowledge) and patient review text.
How do I build a doctor lead list with ratings?
Use search mode with a location (state or state/city slug) and optional specialty, then read the default dataset: each profile row carries phone, address fields, specialty, reviewCount, averageScore and the five rating dimensions.
SEO Keywords
ratemds scraper, ratemds reviews api, ratemds api, ratemds scraper apify, scrape ratemds.com doctor data, doctor reviews data api, healthcare provider reviews api, physician ratings data, healthcare review monitoring, reputation management for doctors, online reputation management for doctors, patient sentiment analysis, healthcare lead generation, doctor leads with ratings and reviews, provider data enrichment, physician market research, doctor rating sites, physician rating websites, best doctor rating sites, compare doctor reviews, scrape doctor reviews for research dataset, medical practice marketing online reviews, clinic reputation monitoring, best rated doctors in city, doctor ratings near me
For AI Agents & LLM Apps
Purpose: extract doctor profiles and patient reviews from RateMDs.com (US + Canada) into two structured datasets.
Minimal working input:
{"mode": "search","location": "tx/houston","proxy": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Variant — profile mode: {"mode": "profile", "profileUrls": ["https://www.ratemds.com/doctor-ratings/dr-jane-doe-toronto-on/"]}
Output fields: 33 profile fields in the default dataset, 15 review fields in the reviews dataset — full inventory with groupings in the Output Fields section above.
Behaviors an agent should know:
modeis the only required field:search(default) crawls listing pages,profilefetchesprofileUrlsdirectly. US + Canada only (country:us/ca/both, defaultboth); a country prefix inlocationis stripped automatically.- Dual-dataset writes: profiles go to the default dataset, reviews to the separate
reviewsdataset; both URLs are exposed atoutput.profilesandoutput.reviews. If the second storage cannot be written (restricted token), reviews fall back into the default dataset marked"type": "review". includeReviewsdefaults totrue— each stored review is a billedReviewevent. Cost-relevant defaults if unset:maxItems100,maxPages10,maxReviewsPerDoctor5;0means unlimited (capped by Apify limits).maxConcurrency(1-20, default 10) fills parallel slots immediately; those requests share up to 3 sticky residential sessions (PoW solved once per session). The residential proxy is mandatory (datacenter IPs get HTTP 406 and the run fails). Use 1024 MB+ memory for 10+ parallel slots.
Billing (pay-per-event): Doctor $0.0015 per profile (DIAMOND $0.0014) + Review $0.00015 per review (DIAMOND $0.00014) + Actor Start $0.00005.
Legal & Compliance Disclaimer
This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by RateMDs or its operators.
It accesses only publicly available RateMDs pages — no login, paywall or authentication bypass. It uses residential proxies and solves the site's public proof-of-work challenge to retrieve those public pages.
You are solely responsible for complying with RateMDs' Terms of Service and applicable data-protection laws (GDPR, CCPA where relevant) when collecting, storing or using the data. Output includes doctor names, practice contact details and patient review content — all publicly posted on RateMDs. Do not use personal contact data for unsolicited commercial outreach in violation of applicable law, and do not represent scraped ratings or reviews as verified medical advice.