# WhichSchoolAdvisor Scraper · Fees, Ratings & Contacts (`corent1robert/whichschooladvisor-scraper`) Actor

Turn WhichSchoolAdvisor.com into a spreadsheet: fees, inspection ratings, curriculum, address and published contacts. One school, a city listing, or a worldwide catalogue. No login.

- **URL**: https://apify.com/corent1robert/whichschooladvisor-scraper.md
- **Developed by:** [Corentin Robert](https://apify.com/corent1robert) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## WhichSchoolAdvisor Scraper

**Build a clean spreadsheet of international schools from WhichSchoolAdvisor — fees, inspection ratings, and published contacts — without copying pages by hand.**

This Actor reads public school profiles on [whichschooladvisor.com](https://whichschooladvisor.com) and writes **one row per school**. Paste a shortlist, target a city listing, or export a whole market (UAE, Singapore, Hong Kong, Thailand, UK, Vietnam, Saudi Arabia).

**No login. No API key. No account on WhichSchoolAdvisor.** Contacts are copied only when the school publishes them (on the profile, the contact tab, or its own website). They are never invented.

***

### Who is this for?

| You are… | Typical goal | Suggested setup |
|---|---|---|
| Relocation / mobility team | Comparable shortlist with fees and ratings | **Individual** — paste the schools on the family's list |
| Education consultant / placement agency | Keep a city or GCC portfolio up to date | **Listing** — paste a city or country search URL |
| Edtech or school platform | Seed or enrich a catalogue | **Worldwide** — then **Start** |
| Market research | Compare fee bands, curricula, inspection ratings | **Listing** or **Catalogue** with **Max schools** at 0 on a paid plan |
| CRM / outbound | Public emails and phones when the school lists them | Keep **Find published email & phone** on |

**What you get by default** — name, city, country, curriculum, inspection rating, fee range when shown, website, address, map coordinates, and the directory rating.

**When to enable website contacts** — WhichSchoolAdvisor often hides the mailbox behind a “request information” form. Leave the option on to copy a mailbox or phone **only if it appears on the school's own site**.

### Ready-made examples

| Example | Use it when |
|---|---|
| [Dubai school profile](https://apify.com/corent1robert/whichschooladvisor-scraper/examples/dubai-school-profile) | One school — fees, rating, published contacts |
| [Dubai city sample](https://apify.com/corent1robert/whichschooladvisor-scraper/examples/dubai-city-schools-sample) | Up to 20 schools from the Dubai listing |
| [Singapore schools sample](https://apify.com/corent1robert/whichschooladvisor-scraper/examples/singapore-schools-sample) | Up to 20 Singapore schools with contact columns |
| [UAE catalogue sample](https://apify.com/corent1robert/whichschooladvisor-scraper/examples/uae-catalogue-sample) | 20 rows from the UAE directory |
| [Worldwide catalogue](https://apify.com/corent1robert/whichschooladvisor-scraper/examples/worldwide-whichschooladvisor-catalogue) | Every WhichSchoolAdvisor market. Paid plan. **Max schools** 0 |

***

### What it extracts

| Theme | Typical columns |
|--------|-----------------|
| Identity | Name, profile URL, city, community, country, address, map coordinates |
| Programme | Curriculum, school type, phase, gender, opening year, principal, owner |
| Quality | Inspection rating, WhichSchoolAdvisor rating and review count |
| Cost | Average annual fee, fee range, currency, price band |
| Contact | Website; email and phone when published |

Empty cells usually mean that school did not publish that detail.

***

### How to use

1. Pick a **Mode**: Individual (school URLs), Listing (city or country search URLs), Catalogue (selected markets), or **Worldwide**.
2. Set **Max schools**. Free plan: **20 per run**. Paid plans: **0** = no ceiling.
3. Click **Start**. Download **CSV**, **Excel**, or **JSON** from the dataset.

**Full worldwide dump:** pick **Worldwide**, click **Start**. You can leave Markets and Max schools as they are. Default timeout is 4 hours. Free Apify accounts still stop at 20 rows.

***

### Input

| Field | What it does |
|--------|----------------|
| Mode | Individual / Listing / Catalogue / Worldwide |
| School URLs | Profile URLs (Individual) |
| Listing URLs | e.g. `https://whichschooladvisor.com/uae/schools-by-city/dubai` |
| Markets | Catalogue only. Ignored in **Worldwide** |
| Max schools | Cap; `0` = unlimited on paid plans. **Free plan: 20 / run**. Worldwide lifts the 20 default. |
| Find published email & phone | Scan the school website when the directory hides contacts |
| URLs to skip | Optional exclusions |

**API-only:** `maxConcurrency` (default 8, max 20), `proxyConfiguration` (cloud runs use Apify proxy by default), `verboseLogs`.

***

### Example output

```json
{
  "url": "https://whichschooladvisor.com/uae/school-review/ambassador-school",
  "name": "Ambassador School",
  "country": "United Arab Emirates",
  "city": "Dubai",
  "community": "Al Mankhool, Dubai",
  "curriculum": "CISCE, EYFS",
  "inspection_rating": "Very good",
  "fees_average": "30500",
  "fees_range": "19225-45750",
  "fees_currency": "AED",
  "price_band": "Mid-range",
  "website": "http://www.ambassadorschool.com/",
  "email": "admissions@ambassadorschool.com",
  "phone": "+971 4 398 3535"
}
```

***

### Pricing

Pay per school row in the dataset. Platform compute is billed to you on top (PPE platform usage paid by user).

| | Price |
|---|---|
| **result** (one school) | **$0.00699** (~$7 per 1,000 schools) |

| Scenario | Rows | Approx. cost |
|---|---|---|
| Try one school | 1 | $0.01 |
| City sample | 20 | $0.14 |
| Full UAE catalogue (~600) | 600 | $4.19 |
| All markets (~1,200) | 1,200 | $8.39 |

Website contact scans add compute time, not extra PPE events.

***

### Performance

HTTP-only (no browser). A 20-school sample typically finishes in a few minutes at 1024 MB. A full UAE catalogue is a longer run — raise the Timeout if you set **Max schools** to 0.

***

### FAQ

**Do I need a WhichSchoolAdvisor account?** No.

**Will you invent emails?** No. If the school did not publish a mailbox, the cell stays empty.

**What if a listing page has more than 20 schools?** Free plan stops at 20. Paid plans follow **Max schools** (`0` = no ceiling).

**Which markets are covered?** UAE, Singapore, Hong Kong, Thailand, United Kingdom, Vietnam, and Saudi Arabia — the public WhichSchoolAdvisor country sites.

***

### Legal / compliance

This Actor reads **public web pages**. You are responsible for how you use the data (outreach, storage, local law). Do not use results to spam. Contact: <corentin@outreacher.fr>.

***

### Local development

```bash
cd whichschooladvisor-scraper
npm install
npm test
apify run --purge --input-file=./.actor/INPUT.json
```

***

### Support

Questions or a broken selector after a site redesign: **corentin@outreacher.fr**.

# Actor input Schema

## `mode` (type: `string`):

**Individual** — paste school profile URLs (fastest first run).

**Listing** — every school on a city or country search page.

**Catalogue** — all schools in the markets you select.

**Worldwide** — every WhichSchoolAdvisor market (UAE, Singapore, Hong Kong, Thailand, UK, Vietnam, Saudi Arabia). Paid plan.

## `urlsToScrape` (type: `array`):

One profile URL per line. Used when mode is **Individual**.

## `listingUrls` (type: `array`):

City or country search pages, e.g. https://whichschooladvisor.com/uae/schools-by-city/dubai. Used when mode is **Listing**.

## `countries` (type: `array`):

WhichSchoolAdvisor markets to export. Used when mode is **Catalogue**. Ignored when mode is **Worldwide**.

## `maxSchools` (type: `integer`):

How many schools to export. **0** = no ceiling (paid plans). Free plan is capped at **20** per run.

## `enrichContacts` (type: `boolean`):

When the directory hides contacts, open the school's own website and copy a published mailbox or phone if they are on the page. Never invented. Turn off for a faster fees-only export.

## `urlsToSkip` (type: `array`):

Optional. School profile URLs to exclude after discovery.

## Actor input object example

```json
{
  "mode": "individual",
  "urlsToScrape": [
    "https://whichschooladvisor.com/uae/school-review/ambassador-school"
  ],
  "maxSchools": 20,
  "enrichContacts": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per school — fees, ratings, curriculum, address and published contacts

## `runLog` (type: `string`):

Progress bar lines and status updated during the run

# 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 = {
    "mode": "individual",
    "urlsToScrape": [
        "https://whichschooladvisor.com/uae/school-review/ambassador-school"
    ],
    "maxSchools": 20,
    "enrichContacts": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("corent1robert/whichschooladvisor-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 = {
    "mode": "individual",
    "urlsToScrape": ["https://whichschooladvisor.com/uae/school-review/ambassador-school"],
    "maxSchools": 20,
    "enrichContacts": True,
}

# Run the Actor and wait for it to finish
run = client.actor("corent1robert/whichschooladvisor-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 '{
  "mode": "individual",
  "urlsToScrape": [
    "https://whichschooladvisor.com/uae/school-review/ambassador-school"
  ],
  "maxSchools": 20,
  "enrichContacts": true
}' |
apify call corent1robert/whichschooladvisor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,corent1robert/whichschooladvisor-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/9m8yN4S81gYmbySxh/builds/zxTuiEpQKyjYsAXVg/openapi.json
