UK Vet Practice Leads - RCVS Register
Pricing
$1.50 / 1,000 per practice returneds
UK Vet Practice Leads - RCVS Register
From $1.50 per 1,000 practices, no start fee. All 5,647 UK veterinary practices on the RCVS register: direct email (79%), phone (84%), full address, postcode, lat/lng and RCVS accreditation tier. Optional detail-page enrichment adds species treated, opening hours and facilities. No API key.
Pricing
$1.50 / 1,000 per practice returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
🐾 UK Vet Practice Leads — the full RCVS register
Every veterinary practice registered with the Royal College of Veterinary Surgeons — the statutory regulator every UK vet practice must be on. 5,647 practices, with a direct email on four in five.
Name · email · phone · full address · postcode · lat/lng · RCVS accreditation tier · Practice Standards modules. Optionally: species treated, opening hours and facilities.
No API key. No account. No login. $0.0015 per practice, no start fee — the whole UK register is $8.47.
📊 The measured numbers
These are not a sample and not an estimate. The whole register was pulled and counted —
all 5,647 rows, 565 requests, measured 1m12s and 2m00s on two separate full sweeps, 0 non-200 responses on either. Empty strings,
whitespace, HTML-only values and the literal N/A were all counted as not filled.
| field | fill | count | notes |
|---|---|---|---|
practiceName · practiceUrl · practiceSlug · practiceId | 100% | 5,647 | all 5,647 distinct |
addressLine1 · postcode · postcodeArea · addressFull | 100% | 5,647 | postcode split out of an HTML blob |
latitude · longitude | 100% | 5,647 | every value inside the UK bounding box |
rcvsAccreditation | 99.98% | 5,646 | 3,589 Accredited · 218 in progress · 1,839 non-accredited |
town | 99.9% | 5,644 | |
county | 93.6% | 5,286 | London practices publish none |
phone | 86.6% | 4,889 | |
phoneE164 | 86.0% | 4,858 | +44… for diallers |
email | 81.9% | 4,623 | 2,099 distinct domains |
accreditations · accreditationsText | 63.8% | 3,600 | Practice Standards modules |
website | 4.9% | 279 | sparse — see honest limits |
awards · awardsText | 2.9% | 161 | sparse |
The email column is the product, so it was checked past "non-empty": all 4,623 pass a strict
address test, and 2,099 distinct domains across 4,623 addresses proves these are real
per-practice mailboxes rather than one chain address repeated. Even the corporate ones are
branch-specific — llandaff.north@medivet.co.uk, northwich@vetsforpets.com,
slough@companioncare.co.uk — which is exactly what a lead list needs.
⚠️ The register comes in two blocks — read this before setting a cap
RCVS does not return these 5,647 practices in a uniform order. Measured across the full census:
| rows | phone | website | ||
|---|---|---|---|---|
| First block | 0–319 (320 practices) | 0% | 0% | 85.6% |
| Main block | 320–5,646 (5,327 practices) | 86.8% | 91.8% | 0.1% |
The first email appears at row 327. 274 of the register's 279 websites sit inside that first block.
What this means for you: a small run with no filter reads only the first block and returns practices with no email addresses at all. That is the source's ordering, not a bug, and this Actor will not quietly reshuffle it on you — but it does mean:
If you want leads, set
requireEmail: true. Any filter makes the Actor read the whole register and deliver only matching rows — sorequireEmail: truewithmaxPractices: 1000gives you 1,000 real leads drawn from all 5,647 practices, not the first 1,000 rows.
Every run also reports its own measured fill in RUN_SUMMARY.fieldFill, so you never have to
take this README's word for what you actually received.
Optional: species, hours and facilities
Measured over 93 real practice pages:
| field | fill |
|---|---|
animalsTreated | 97.8% (91/93) |
facilities | 69.9% (65/93) |
openingTimes | 67.7% (63/93) |
developmentAndTraining | 63.4% (59/93) |
These four do not exist in the register's listing API — only on each practice's own page. Turn
on enrichFromDetailPages, or just set a species filter, which turns it on for you. It costs one
extra request per candidate: 5,647 instead of 565 for the whole register.
📋 What one row looks like
A real row from the verified run (animalsTreated: ["Horses"], requireEmail: true):
{"practiceId": "5e9ed532-4ca1-4962-bb4f-e25cfdcb8d0c","practiceName": "The Sussex Equine Hospital Ltd","practiceUrl": "https://www.rcvs.org.uk/animal-owners/find-a-vet/practices/the-sussex-equine-hospital-ltd-pulboroughrh20-3bb","email": "info@sussexequinehospital.co.uk","emailDomain": "sussexequinehospital.co.uk","phone": "01903 883050","phoneE164": "+441903883050","website": null,"addressLine1": "Billingshurst Road","town": "PULBOROUGH","postcode": "RH20 3BB","postcodeArea": "RH","county": "West Sussex","country": "United Kingdom","addressFull": "Billingshurst Road, Ashington, PULBOROUGH RH20 3BB West Sussex, United Kingdom","latitude": 50.9476473,"longitude": -0.3957418,"rcvsAccreditation": "Accredited Practice","isAccredited": true,"accreditations": ["Equine Emergency Service Clinic", "Equine Veterinary Hospital"],"animalsTreated": ["Horses"],"facilities": ["Client Car Park", "Disabled Public Access", "Out Of Hours", "Open At Weekends"],"developmentAndTraining": ["Extra Mural Studies (EMS)", "VetGDP"],"openingTimes": {"monday": "08:30-17:30", "tuesday": "08:30-17:30", "wednesday": "08:30-17:30","thursday": "08:30-17:30", "friday": "08:30-17:30","saturday": "08:30-12:30", "sunday": "Closed"}}
🎯 Who buys this
- Practice-management software (ezyVet, Provet Cloud, Vetstoria) — the full UK TAM, segmented by
accreditation tier and by small-animal vs equine vs farm-animal via
accreditationModules - Veterinary wholesalers and pharma reps — territory lists by
postcodeAreasorcounties, withlatitude/longitudefor route planning - Locum and recruitment agencies — filter to
VetGDPandExtra Mural Studies (EMS)practices, the ones that actively take and train new graduates - Consolidator M&A desks (IVC Evidensia, VetPartners, CVS) — independents stand out as the
practices whose
emailDomainis their own rather than a group domain, andawardsflags the Practice Standards high performers
⚙️ Filtering, and what it costs
The register's API has no server-side filtering at all. Measured 2026-09-16:
animals_treated=209, f[0]=animals_treated:209, animals_treated[]=209,
filters[animals_treated][]=209, facets[animals_treated]=209, rcvs_accreditation=accredited,
keyword=, search= and a JSON POST body all return HTTP 200 with meta.count still 5,647
and the identical first ten items. Every parameter is silently ignored.
So all filtering here runs on our side, after the fetch. A narrow filter costs the same crawl as a wide one — but you are only charged for rows you actually receive. A filter matching 40 practices costs 40 × $0.0015 = $0.06, whatever the crawl cost us.
| filter | stage | cost |
|---|---|---|
requireEmail · requirePhone · requireWebsite | listing | free |
accreditationTier · accreditationModules | listing | free |
postcodeAreas · counties · nameOrTownIncludes | listing | free |
animalsTreated · facilities · developmentAndTraining | detail page | 1 request per candidate |
Setting a species, facility or training filter switches detail enrichment on automatically and
says so in the log — those fields cannot be answered from the listing, and silently returning
everything would look like a filter that ran. RUN_SUMMARY reports detailPagesFetched against
delivered so you can see the ratio (measured example: 93 pages fetched to deliver 15 equine
practices).
🤖 robots.txt and crawl rate
https://www.rcvs.org.uk/robots.txt declares, verbatim:
User-agent: *Crawl-delay: 10
No Disallow covers /api/ or /animal-owners/. The Crawl-delay: 10 is a courtesy
directive, and this Actor does not enforce it by default — it runs 5 concurrent requests with no
delay, which takes one to two minutes for the whole register. To honour the declared delay exactly,
set maxConcurrency: 1 and requestDelayMs: 10000; the full register then takes about 94
minutes. That is your call, and it is stated here rather than buried.
For the record, measured during the build: 0 non-200 responses across ~1,200 requests, including
20 fired back-to-back with no delay and a full 565-page sweep at concurrency 8. No rate limit, no
CAPTCHA, no JS challenge. A bare curl with its default user agent and a full browser header set
returned byte-identical bodies from the same URL.
🧨 Four traps in this source, and what this Actor does about them
1. The records are hidden behind sentinels. The listing API returns items shaped
{id, bundle, type, markup} — no practice fields on the item at all. The real record is a string
inside markup, between %%JSON_START%% and %%JSON_END%%. A scraper that reads item.email gets
undefined on every row, ships a dataset where every column is empty, and still reports a
green build and a SUCCEEDED run. This Actor unwraps the sentinels and fails the run if more than
2% of items stop parsing.
2. The 13 species are a filter menu, not practice data. meta.facets[animals_treated] lists
Aquatic, Birds, Camelids, Cats, Cattle, Deer, Dogs, Exotic/Wild, Horses, Pigs, Poultry, Sheep/Goats
and Small Mammals — identically on every page. It describes the website's filter UI. There is no
per-practice species field on any of the 5,647 records. Real per-practice species exist only on the
detail page, which is why animalsTreated is an enrichment field and not a free one.
3. The address is an HTML blob with the postcode buried in it. address arrives as a <p>
whose middle line reads MELTON MOWBRAY LE13 1JE Leicestershire — town, postcode and county mashed
together with no separator of any kind. The postcode is the only anchor: everything before it is the
town, everything after is the county. That is the real parsing work here, and it is why town,
postcode and county are separate columns instead of one unusable string.
4. The email on the practice page is often RCVS's own. Detail pages Cloudflare-obfuscate emails
(data-cfemail, rendering as [email protected]), and the obfuscation is a trivial XOR. But a
"grab the first email on the page" enrichment was built, measured over 21 pages, and cut: the
detail page added zero addresses the listing API did not already have. Thirteen of thirteen
matched exactly — and the eight practices with no listing email carried only info@rcvs.org.uk,
the college's own switchboard, sitting beside the college's own postal address. That column would
have been wrong on 38% of rows while looking perfectly filled. This Actor ships no such field.
⚠️ Honest limits
- The two-block ordering, above. It is the single thing most likely to surprise you. An
unfiltered capped run returns email-less rows. Use
requireEmail: true. websiteis 4.9% filled (279 of 5,647), and 274 of those 279 are in the first block — so in practice you can have websites or emails, almost never both. If you need practice websites, this is not the source.awardsis 2.9% filled (161 of 5,647). Genuinely useful for spotting Practice Standards high performers, genuinely rare.countyis 93.6%, and the gap is mostly London. Those rows havecounty: null, never a guessed value. UsepostcodeAreasfor London.townis upper-cased the way the register writes it (MELTON MOWBRAY). It is deliberately not title-cased: that would turnST. NEOTSandBURY ST EDMUNDSinto something wrong, and a mis-cased town in a mail merge is worse than an honestly shouty one. Three practices in 5,647 publish no separate town line at all; those arenull.- 31 phone numbers in 5,647 resist normalisation — they hold two numbers in one field
(
01472 347054/362 821), an Irish number, or a malformed one.phonekeeps the text exactly;phoneE164isnullfor them rather than a spliced number that would misdial. openingTimesignores the per-day comments. The register sometimes adds a note like "Closed between 9-2:30" beside a day's hours. Only the hours are captured.- A practice that publishes no species list is excluded by a species filter, not included as a maybe. 2.2% of practice pages have no species section at all.
- Accreditation modules are split against a closed vocabulary. The register concatenates them
with no delimiter, so the split is longest-match plus a residual check. If RCVS adds a module this
build does not know,
accreditationsisnullandaccreditationsTextstill carries the raw string — an honest "not split" rather than a wrong split. This is not hypothetical: the full census found a module absent from the initial sample (Equine Veterinary Hospital, 29 practices) and it degraded exactly that way before being added. Current census: 0 unsplit. - The listing view id is a magic constant. The register is a Drupal view at
/api/listing/6194. If RCVS repoints that id, the run fails loudly — it asserts the register still reports at least 4,000 practices — rather than quietly delivering ten rows from some other view. countryis alwaysUnited Kingdom. It is 100% filled and 100% constant; it ships because a CRM import wants the column, not because it carries information.
💵 Pricing
| Per practice delivered | $0.0015 |
| Start fee | none |
| 1,000 practices | $1.50 per 1,000 |
| The whole UK register (5,647) | $8.47 |
| A run that matches nothing | $0.00 |
You are charged once per practice delivered to your dataset. Practices excluded by your filters
are never delivered and never charged. A practice page we could not reach is never charged — it is
reported separately in RUN_SUMMARY from "this practice publishes no species", because to someone
working a lead list those mean different things.
❓ FAQ
What is the RCVS register? The Royal College of Veterinary Surgeons is the UK's statutory regulator for veterinary surgeons and veterinary nurses. Its "Find a Vet" register lists practice premises. It is the closest thing there is to a complete list of UK vet practices.
Is this all UK vet practices?
It is every practice on the RCVS "Find a Vet" register — 5,647 when this was built, and the count
moves (a recon a fortnight earlier read 5,646). The run reports the live total in RUN_SUMMARY.
How long does a full run take?
Measured: 1m12s and 2m00s on two separate full sweeps of all 5,647 practices — 565 requests, because the page size is hard-locked at
10 and cannot be raised (items_per_page, page_size and limit are all silently ignored). With
detail enrichment it is 6,212 requests and takes considerably longer. Honouring the declared
Crawl-delay: 10 takes about 94 minutes.
Why did my 100-row run come back with no email addresses?
Because of the two-block ordering described above — an unfiltered run reads the first 320 practices,
which have none. Set requireEmail: true.
Can I get just equine or farm-animal practices?
Yes, and cheaply. Use accreditationModules with Equine General Practice (Ambulatory),
Equine Veterinary Hospital, Farm Animal General Practice or the Core Standards (…) variants —
that comes from the listing and needs no detail-page fetch. It covers 63.8% of practices. For exact
species coverage use animalsTreated, which enriches from detail pages.
Can I get only accredited practices?
Yes — accreditationTier: ["Accredited Practice"]. Measured: 3,589 of 5,647.
Do I need a proxy? No. The register answered 200 on every request during the build with no proxy and no browser. Apify Proxy (datacenter) is the default anyway, for IP hygiene.
Do I need an API key or a login? No. Everything here is the public register as served to any visitor.
Why is website so empty?
Because the register is like that. It is reported honestly at 4.9% rather than quietly dropped or
padded.
What happens if a request fails?
It is retried on a fresh proxy session. A non-200 is treated as a transport failure, never as the
end of the data. Pages that stay unreachable are listed in RUN_SUMMARY, and if more than a quarter
of the walk fails, the run fails rather than handing you a partial register that looks complete.
Will a run ever silently return a short register? No. An unfiltered full sweep floor-asserts against the count the register itself declares and fails if it recovers less than 98% of it. The verified run recovered 5,647 of 5,647.
How do I get species, hours and facilities?
Set enrichFromDetailPages: true, or just set a species/facility/training filter — that switches it
on automatically.
Can I re-run this to track changes?
Yes. practiceId and practiceSlug are stable keys, so two runs diff cleanly.
⚖️ Legal
This Actor reads the public RCVS "Find a Vet" register — the same pages and the same JSON any visitor's browser receives. No login, no account, no credential, no paywall is involved.
robots.txt is quoted verbatim above: User-agent: * / Crawl-delay: 10, with no Disallow
covering the paths used. The crawl-delay knob is exposed as an input so you can honour it exactly.
The register contains business contact details — practice premises, not individuals' personal data. You are responsible for your own use of it, including UK GDPR and PECR obligations around marketing to business contacts.
Not affiliated with, endorsed by, or connected to the Royal College of Veterinary Surgeons.