# UK Vet Practice Leads - RCVS Register (`scrapersdelight/rcvs-vet-practices-scraper`) Actor

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.

- **URL**: https://apify.com/scrapersdelight/rcvs-vet-practices-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 per practice returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🐾 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 | email | 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 — so `requireEmail: true` with `maxPractices: 1000` gives
> 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`):

```json
{
  "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 `postcodeAreas` or `counties`,
  with `latitude`/`longitude` for route planning
- **Locum and recruitment agencies** — filter to `VetGDP` and `Extra 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 `emailDomain` is their own rather than a group domain, and `awards` flags 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`.
- **`website` is 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.
- **`awards` is 2.9% filled** (161 of 5,647). Genuinely useful for spotting Practice Standards high
  performers, genuinely rare.
- **`county` is 93.6%, and the gap is mostly London.** Those rows have `county: null`, never a
  guessed value. Use `postcodeAreas` for London.
- **`town` is upper-cased** the way the register writes it (`MELTON MOWBRAY`). It is deliberately
  not title-cased: that would turn `ST. NEOTS` and `BURY ST EDMUNDS` into 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 are `null`.
- **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. `phone` keeps the text exactly;
  `phoneE164` is `null` for them rather than a spliced number that would misdial.
- **`openingTimes` ignores 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, `accreditations` is `null` and `accreditationsText` still 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.
- **`country` is always `United 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.*

# Actor input Schema

## `maxPractices` (type: `integer`):

Cap on practices delivered - and therefore charged. 0 means the whole register (5,647 practices, 565 requests, measured 2m0s). Without a filter the crawl stops as soon as this many rows are in hand - and because RCVS returns the register in two blocks, an unfiltered capped run reads only the first 320 practices, which have websites but NO email or phone. Pair a cap with requireEmail to sample the whole register instead.

## `requireEmail` (type: `boolean`):

Drop practices that publish no email address. Measured over a full 5,647-row census: 81.9% have one (4,623 practices). STRONGLY RECOMMENDED when you also set maxPractices - the register returns its first 320 practices in a block that has no email addresses at all, so a small unfiltered run reads only those. With any filter set, the whole register is read and only matching rows are delivered and charged.

## `requirePhone` (type: `boolean`):

Drop practices that publish no phone number. Measured over the full register: 86.6% (4,889 practices).

## `requireWebsite` (type: `boolean`):

Drop practices that publish no website. WARNING - the register almost never carries one: measured over the full register it is 4.9% (279 practices), and 274 of those 279 sit in the first 320 records, which carry no email or phone.

## `accreditationTier` (type: `array`):

Filter by the practice's standing in the RCVS Practice Standards Scheme. Leave empty for all three.

## `accreditationModules` (type: `array`):

Filter by the specific Practice Standards Scheme modules a practice holds - the cheap way to separate small-animal from equine and farm-animal practices, because it comes from the listing and needs no detail-page fetch. Measured over the full register: 63.8% of practices list at least one module (3,600).

## `postcodeAreas` (type: `array`):

Filter to one or more UK postcode AREAS - the letters only, such as SW, M, LS, EH, CF. Matched exactly, so M does not also return ME.

## `counties` (type: `array`):

Filter by county exactly as the register writes it, for example Leicestershire, West Sussex, Argyll. Measured over the full register: 93.6% (5,286) - London practices usually publish no county, so use postcodeAreas for London.

## `nameOrTownIncludes` (type: `string`):

Free-text match against the practice name, town, county and postcode. Case-insensitive.

## `enrichFromDetailPages` (type: `boolean`):

Fetch each matching practice's own RCVS page to add species treated, opening hours, facilities and training status. These four fields DO NOT exist in the register's listing API - this is the only way to get them, and it costs one extra request per practice (5,647 for the full register instead of 565). Off by default.

## `animalsTreated` (type: `array`):

Keep only practices that treat these species. Requires detail-page enrichment and switches it on automatically. Measured: 97.8% of practice pages publish a species list; a practice that publishes none is excluded rather than guessed at.

## `animalsMatchAll` (type: `boolean`):

By default a practice is kept if it treats ANY of the chosen species. Turn this on to require ALL of them.

## `facilities` (type: `array`):

Keep only practices offering ALL of these. Requires detail-page enrichment and switches it on automatically. Measured: 69.9% of practice pages publish a facilities list.

## `developmentAndTraining` (type: `array`):

Keep only practices that take veterinary students (EMS) or are RCVS Approved Graduate Development Practices (VetGDP). Requires detail-page enrichment and switches it on automatically. Measured: 63.4% of practice pages publish this.

## `maxConcurrency` (type: `integer`):

Parallel requests to rcvs.org.uk. The register's robots.txt declares 'Crawl-delay: 10' - set this to 1 and requestDelayMs to 10000 to honour it exactly, which takes about 94 minutes for the full register.

## `requestDelayMs` (type: `integer`):

Pause between requests. 0 by default. Set to 10000 with maxConcurrency 1 to match the Crawl-delay the site declares.

## `proxyConfiguration` (type: `object`):

Apify Proxy. Datacenter is plenty - the register served 200 on every request during testing, with no anti-bot challenge and no rate limit.

## Actor input object example

```json
{
  "maxPractices": 60,
  "requireEmail": true,
  "requirePhone": false,
  "requireWebsite": false,
  "accreditationTier": [],
  "accreditationModules": [],
  "postcodeAreas": [],
  "counties": [],
  "enrichFromDetailPages": false,
  "animalsTreated": [],
  "animalsMatchAll": false,
  "facilities": [],
  "developmentAndTraining": [],
  "maxConcurrency": 5,
  "requestDelayMs": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per UK veterinary practice on the RCVS register: name, email, phone, full address, postcode, coordinates, accreditation tier and Practice Standards modules - plus species treated, opening hours and facilities when detail-page enrichment is on.

## `runSummary` (type: `string`):

RUN\_SUMMARY: how much of the register was read, how many rows were delivered and charged, and - kept separately - unreachable listing pages, unreachable practice pages, unparseable items and practices that publish no detail sections. None of those four is charged.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxPractices": 60,
    "requireEmail": true,
    "enrichFromDetailPages": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/rcvs-vet-practices-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "maxPractices": 60,
    "requireEmail": True,
    "enrichFromDetailPages": False,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/rcvs-vet-practices-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxPractices": 60,
  "requireEmail": true,
  "enrichFromDetailPages": false
}' |
apify call scrapersdelight/rcvs-vet-practices-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/rcvs-vet-practices-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2K36U4KEg8M682UJi/builds/ecQCqFe7bD9ch1W9I/openapi.json
