# Childcare AU: Centres, Fees, Vacancies & NQS Ratings (`abotapi/careforkids-com-au-scraper`) Actor

Scrape Australia’s largest childcare directory careforkids.com.au with long day care, preschool, family day care, OSHC, and vacation care services. Returns centre profiles with address, fees, ratings, vacancies, features, images, and ACECQA approval numbers.

- **URL**: https://apify.com/abotapi/careforkids-com-au-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 96.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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?

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

## CareForKids.com.au Scraper: Childcare Centres, Fees, Vacancies & Ratings

CareForKids.com.au Scraper turns Australia's largest childcare directory into structured data. Search any suburb and postcode across long day care, family day care, preschool, occasional care, before-school, after-school and vacation care, or paste any careforkids.com.au link straight from a browser. Every centre comes with name, address, GPS, phone, daily fee, NQS quality rating, parent rating, vacancy availability and a feature list from the search results, and switching on detail fetching adds the full fee table by age band, day-by-day vacancy schedule, all seven NQS quality areas, gallery images, contact name and hours, social links, provider group, the ACECQA service approval number and parent reviews. Flip to reviews-only output for one row per parent review instead of one per centre. Resume an interrupted multi-suburb sweep, or turn on incremental mode to monitor the same search on a schedule and get back only what changed. Export to JSON, CSV or Excel, or read the dataset through the API.

### Why This Scraper?

- **Two ways in.** Search mode sweeps any suburb + postcode across one or more care types in a single run; URL mode accepts a pasted search page or a single centre link straight from a browser.
- **A whole suburb in one page.** Each suburb + postcode combination returns every centre CareForKids lists there in one page fetch, so a single run already covers a full locality without walking extra pages.
- **Full profile on demand.** Switch on detail fetching for the complete fee table by age band, day-by-day vacancy schedule, all seven NQS quality area ratings, gallery images, contact name and hours, socials, provider group and the ACECQA service approval number.
- **Reviews as their own feed.** Switch to reviews-only output and get one row per parent review (name, rating, date, full text, source, avatar) with the centre's context attached, instead of one row per centre.
- **Filter before you pay.** Verified-only, has-vacancies, minimum rating and maximum daily fee narrow results in Search mode and on any pasted URL, including a single centre link.
- **Built for monitoring.** Resume a large multi-suburb sweep that got interrupted, or turn on incremental mode to schedule the same search and get back only new, changed, reappeared or expired centres.

### Use Cases

- **Parents and relocation planners:** compare fees, vacancies and NQS ratings across a shortlist of suburbs before enrolling.
- **Childcare operators and franchise groups:** track competitor pricing, vacancy trends and parent reviews in nearby suburbs.
- **Directory and comparison sites:** republish a normalized childcare dataset for a suburb or region alongside your own listings.
- **Researchers and policy analysts:** build a dataset of NQS ratings, approved-place capacity and fee bands across a state or region.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `id` | `00000` |
| `url` | `https://www.careforkids.com.au/child-care/00000/sample-centre-suburb-2000` |
| `name` | `Sample Childcare Centre` |
| `suburb` / `postcode` / `state` | `Sample Suburb` / `2000` / `NSW` |
| `address` | `Sample Address, Sample Suburb, NSW` |
| `latitude` / `longitude` | `-33.0000` / `151.0000` |
| `phone` | `+61 2 0000 0000` |
| `rating` / `reviewCount` | `4.5` / `0` |
| `dailyFee` | `200` |
| `hasVacancies` | `true` |
| `isVerified` | `true` |
| `listingType` | `Standard` |
| `careTypes` | `["Long Day Care", "Preschool"]` |
| `requestedCareType` | `longdaycare` |
| `services` | `["Sample Service A", "Sample Service B"]` |
| `nqsRating` | `Meeting` |
| `providerGroup` | `Sample Provider Group` |
| `serviceApprovalNumber` | `SE-00000000` |
| `approvedPlaces` | `90` |
| `contactName` / `contactTime` | `Sample Contact, Director` / `7:30am to 6:00pm` |
| `websiteUrl` | `https://www.example.com/sample` |
| `scrapedAt` | `2026-01-01T00:00:00.000Z` |

With Fetch detail pages on, a record also carries a description, Facebook and Instagram links, a logo and gallery image list, the provider's internal group id, a Google Place id, the full fee table (`feeGroups`, by age band), the day-by-day vacancy schedule (`vacancies`), the overall and all-seven-area NQS ratings (`nqsRatingOverall`, `nqsRatingLabel`, `nqsAreaRatings`), highlight bullets, a waitlist flag and URL, an average daily fee, a rating and review count broken out by source, an overnight-care flag, an embedded `reviews` list, and the full source object under `raw`. Reviews-only output (`reviewsOnly: true`) replaces all of this with one row per review: `centreId`, `centreName`, `centreUrl`, `suburb`, `postcode`, `state`, GPS, `reviewerName`, `rating`, `date`, `text`, `avatarUrl`, `source` and `scrapedAt`. With Incremental mode on, every centre record also carries `changeType` (`NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`), `changedFields`, `firstSeenAt` and `lastSeenAt`.

### How to Use

1. Pick a mode: **Search** (list suburb + postcode pairs and care types) or **URL** (paste any careforkids.com.au link).
2. In Search mode, add one or more suburb + postcode pairs and pick care types. In URL mode, paste search-result pages or single centre links. The result filters (Verified centres only, Vacancies only, Minimum rating, Maximum daily fee) apply to both modes and to a single pasted centre link too.
3. Turn on Fetch detail pages for the full profile, or turn on Reviews-only output to get one row per parent review instead.
4. Set Max listings to control run size, click **Start**, then download the dataset or read it through the API.

**Search by suburb + postcode:**

```json
{
  "mode": "search",
  "locations": [
    { "suburb": "Sydney", "postcode": "2000" }
  ],
  "careTypes": ["all"],
  "fetchDetails": false,
  "maxListings": 20
}
```

**Multiple suburbs, specific care types, vacancies only, full profile:**

```json
{
  "mode": "search",
  "locations": [
    { "suburb": "Sydney", "postcode": "2000" },
    { "suburb": "Bondi", "postcode": "2026" },
    { "suburb": "Parramatta", "postcode": "2150" }
  ],
  "careTypes": ["longdaycare", "preschool"],
  "vacanciesOnly": true,
  "fetchDetails": true
}
```

**Supported URL shapes (URL mode):**

| Shape | Example | Notes |
| --- | --- | --- |
| Search listing, all care types | `https://www.careforkids.com.au/child-care/sydney/2000` | Suburb and postcode in the path. |
| Care-type search listing | `https://www.careforkids.com.au/pre-school/sydney/2000` | Prefixes: `family-day-care`, `occasional-care`, `pre-school`, `before-school-care`, `vacation-care`, `after-school-care`. |
| Long day care prefix | `https://www.careforkids.com.au/child-care-centre/melbourne/3000` | The site redirects this to the all-care-types listing, so the run logs a warning and returns all care types. |
| Centre detail page | `https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011` | One centre. |

A trailing slash, tracking parameters (`?utm_...`) and the non-www host all work. Any other shape (other pages, a suburb without postcode in the path, other domains) is skipped with a warning in the run log naming the URL, never a silent empty result.

**URL mode, paste search pages:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.careforkids.com.au/child-care/sydney/2000",
    "https://www.careforkids.com.au/family-day-care/melbourne/3000"
  ],
  "fetchDetails": true
}
```

**Reviews-only output (one record per parent review):**

```json
{
  "mode": "search",
  "locations": [{ "suburb": "Sydney", "postcode": "2000" }],
  "careTypes": ["all"],
  "reviewsOnly": true,
  "maxListings": 50,
  "maxReviewsPerCentre": 10
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/careforkids-com-au-scraper").call(run_input={
    "mode": "search",
    "locations": [{"suburb": "Sydney", "postcode": "2000"}],
    "careTypes": ["all"],
})
for centre in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(centre["name"], centre["suburb"], centre["dailyFee"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/careforkids-com-au-scraper').call({
  mode: 'search',
  locations: [{ suburb: 'Sydney', postcode: '2000' }],
  careTypes: ['all'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted centre-listing run: paste its run or dataset id and the actor seeds every centre id it already collected before scraping starts, so those centres are skipped instead of being re-fetched and re-billed. An id your account can't read fails the run immediately, before anything is scraped, instead of quietly starting an overlapping pull. Because each suburb + postcode combination is a single page fetch with nothing further to page through, Resume's benefit is skipping centres you already have across a large multi-suburb sweep, not resuming a paused walk through one suburb's own results. Does not apply to Reviews-only output.
- **Incremental mode** (`incrementalMode`) is for scheduling the same search again and again. Each centre is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless Emit unchanged is on), `REAPPEARED` or `EXPIRED`. A centre is only ever marked gone, and later eligible to reappear, after a run that scanned the full tracked search end to end (uncapped, not resumed) with Emit expired switched on; a capped, resumed or partially unreachable run leaves the previous state untouched instead of guessing. State key names or shares one monitoring campaign; leave it blank and the actor derives one automatically from your locations, care types, filters and Fetch detail pages setting, so unrelated searches never mix state. Change detection compares every returned field except `scrapedAt` and the volatile `raw.WaitlistUrl` / `raw.SpecialOfferImage` (a per-request routing value and a cache-busting image URL); use Ignore fields when detecting changes to exclude more (matched by field name at any depth; they are still returned, just never counted as a change or listed in `changedFields`). Changing that list does not cause a wave of UPDATED rows, because the saved baseline is re-compared with the current list. Saved baselines from before the Verified-badge and review-cap update migrate silently: a pasted centre whose Verified badge now reads true instead of the old fixed false, and a detail row whose embedded reviews are now cut to the Max reviews per centre cap, are kept as unchanged (not returned, not billed) once, instead of showing up as a one-time wave of updated centres. Does not apply to Reviews-only output.

#### A pasted centre link and the Verified filter

A single pasted centre page still returns the full profile (fees, vacancies, NQS ratings, gallery, contact, reviews) even with Fetch detail pages left off, since that page is the only source of data for a single-centre link; the detail surcharge is only charged when Fetch detail pages is switched on. The centre's verified badge is read from that page, so `isVerified` reflects the centre's real status and Verified centres only keeps or drops a pasted centre link accordingly.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape - the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record - not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify -> Settings -> Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` builds URLs from Locations and Care types; `url` passes through Search URLs directly. |
| `locations` | array | (none; prefill: Sydney 2000) | Search mode only. Each entry is `{ "suburb": "...", "postcode": "0000" }`. Suburb name is slugified automatically. The postcode is optional: with only a suburb name it is looked up on the site, and a name with no match is logged as an error and skipped. Multiple locations supported. |
| `careTypes` | array | `["all"]` | Service types to search. `all` fetches every type in one request. Multi-select: each location x type pair becomes a separate fetch. |
| `verifiedOnly` | boolean | `false` | Drop centres not flagged as verified. Applies in Search mode and to any pasted URL, including a single centre link. |
| `vacanciesOnly` | boolean | `false` | Drop centres reporting no current vacancies. Applies in Search mode and to any pasted URL, including a single centre link. |
| `minRating` | integer | (off) | Minimum 1-5 parent rating. Centres without a rating are kept. Applies in Search mode and to any pasted URL, including a single centre link. |
| `maxDailyFee` | integer | (off) | Maximum advertised average daily fee in AUD. Centres without an advertised fee are kept. Applies in Search mode and to any pasted URL, including a single centre link. |
| `urls` | array | three example URLs (one per shape, listed under Supported URL shapes) | URL mode only. Paste any careforkids.com.au link: a search page, a care-type search page, or a single centre page. Behaviour change: in URL mode, leaving this field untouched now scrapes the three example URLs (one per shape) instead of doing nothing. The four filters above still apply, including to a single pasted centre link. |
| `maxListings` | integer | `20` | Stop after this many centres across all searches. `0` = no cap. |
| `fetchDetails` | boolean | `false` | Fetch each centre's own page for the full fee table, vacancy schedule, NQS quality areas, gallery, contact and socials, ACECQA number, feature list and parent reviews. Forced on when Reviews-only output is on. A meaningful share of centre pages currently don't carry the embedded data this relies on at all, in which case every detail-only field comes back null even though the fetch itself succeeded and is still billed; for a search or category walk the base fields (name, address, phone, GPS) are unaffected since those come from the search results page, but for a pasted single-centre link, which has no other data source, this can leave the whole record null. |
| `reviewsOnly` | boolean | `false` | Emit one row per parent review instead of one per centre. Pairs with either Search or URL mode. |
| `maxReviewsPerCentre` | integer | `20` | Cap on reviews per centre, applied to Reviews-only rows and to the reviews embedded on detail rows. Behaviour change: the default was previously unlimited; `0` now means the ceiling of 1000, and values above 1000 are clamped to 1000. |
| `resumeFromRunId` | string | (none) | Continue one interrupted centre-listing run without re-fetching or re-billing centres it already collected. Does not apply to Reviews-only output. |
| `incrementalMode` | boolean | `false` | Turn on for recurring monitoring of the same search. Classifies each centre as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. Does not apply to Reviews-only output. |
| `stateKey` | string | (none) | Name or share an incremental-mode monitoring campaign. Leave blank to derive one automatically from the search scope. |
| `emitUnchanged` | boolean | `false` | Incremental mode only. Also return (and bill) centres unchanged since the last run. |
| `emitExpired` | boolean | `false` | Incremental mode only. Also return (and bill) centres no longer found, once a run has scanned the full tracked search end to end. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only. Field names (any depth) that never count as a change and are left out of `changedFields`; still returned in the output. |
| `proxy` | object | (none; prefill: Apify Proxy) | Optional proxy configuration. Leave the default unless you need your own routing. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "id": "00000",
  "url": "https://www.careforkids.com.au/child-care/00000/sample-centre-suburb-2000",
  "name": "Sample Childcare Centre",
  "suburb": "Sample Suburb",
  "postcode": "2000",
  "state": "NSW",
  "address": "Sample Address, Sample Suburb, NSW",
  "latitude": -33.0000,
  "longitude": 151.0000,
  "phone": "+61 2 0000 0000",
  "rating": 4.5,
  "reviewCount": 0,
  "dailyFee": 200,
  "hasVacancies": true,
  "isVerified": true,
  "listingType": "Standard",
  "careTypes": ["Long Day Care"],
  "requestedCareType": "longdaycare",
  "services": ["Sample Service A", "Sample Service B"],
  "nqsRating": "Meeting",
  "nqsRatingOverall": "Meeting",
  "nqsRatingLabel": "Meeting National Quality Standard",
  "nqsAreaRatings": [
    "Meeting NQS", "Meeting NQS", "Meeting NQS",
    "Meeting NQS", "Meeting NQS", "Meeting NQS", "Meeting NQS"
  ],
  "providerGroup": "Sample Provider Group",
  "googlePlaceId": "ChIJ0000000000",
  "logoUrl": "https://img-cdn.example.com/api/img?type=UserPhoto&id=00000",
  "galleryImageUrls": [
    "https://img-cdn.example.com/api/img?type=UserImage&id=00001",
    "https://img-cdn.example.com/api/img?type=UserImage&id=00002"
  ],
  "feeGroups": [
    {
      "careType": "Long Day Care",
      "fees": [
        { "fromWeeks": 6, "toYears": 2, "maxPrice": 200, "feeTypeDisplay": "/day" },
        { "fromYears": 2, "toYears": 5, "maxPrice": 200, "feeTypeDisplay": "/day" }
      ]
    }
  ],
  "vacancies": [
    {
      "careType": "Long Day Care",
      "ageGroup": "6 wks to 2 yrs",
      "ageGroupLabel": "Babies",
      "daysOfWeek": [false, true, true, true, true, true, false]
    }
  ],
  "serviceExtras": [
    { "id": 1, "name": "Sample Service Feature", "iconId": "sample-feature" }
  ],
  "highlights": "Sample highlight bullet|Another sample bullet|Final sample bullet",
  "hasWaitlist": false,
  "dailyAverageFee": 200,
  "approvedPlaces": 90,
  "serviceApprovalNumber": "SE-00000000",
  "contactName": "Sample Contact, Director",
  "contactTime": "7:30am to 6:00pm",
  "websiteUrl": "https://www.example.com/sample",
  "facebookUrl": "https://www.facebook.com/sample-childcare-centre",
  "instagramUrl": "https://www.instagram.com/sample_childcare_centre",
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

### Plan Requirement

The default proxy setting uses Australian residential connections, because the site refuses datacenter connections outright. If a connection is refused, retries move to another connection automatically, and the run log says when a backup connection served the pages. Apify free plans do not include residential proxies; on a free plan the run continues on a backup connection where possible, and you can upgrade at https://apify.com/pricing or supply your own proxy URLs.

### FAQ

#### How much does it cost?

You pay per record returned into the dataset. In centre mode that's one charge per centre; turning on Fetch detail pages adds a one-time surcharge on top for each centre record that carries the extra detail-page fields (skipped for a centre that returned no detail data at all); a record suppressed by incremental mode's unchanged or expired settings is never charged. In Reviews-only mode, every review is its own dataset row and is billed as such, plus one detail surcharge for each centre that returned at least one review (a centre with zero reviews skips that surcharge). The **Pricing** tab shows the current rates, and Max listings caps the size, and cost, of any run.

#### Is it legal to scrape CareForKids.com.au?

This actor collects only publicly available childcare directory listings. You are responsible for how you use the data: follow CareForKids.com.au's terms and the laws that apply to you, and get legal advice before any commercial redistribution, especially of contact details or parent reviews.

#### Can I monitor a suburb and get only new or changed centres?

Yes. Schedule the actor and turn on Incremental mode. Each run then returns only new, updated, reappeared or expired centres for that search, and unchanged ones are not billed unless you turn Emit unchanged on. This does not apply to Reviews-only output.

#### What happens when no page can be loaded?

If the run could not load a single page (every connection refused, or the site served nothing usable), it ends as FAILED with a status message saying whether the proxy was refused for your plan or the site could not be reached. It does not finish as SUCCEEDED with an empty dataset. A run where pages loaded but no centre matched (for example a wrong suburb and postcode pair) still finishes normally with 0 centres and a log message: double-check the suburb and 4-digit postcode pair, or try URL mode with a link copied from the site.

#### Does Verified centres only work on a pasted centre link?

Yes. The centre page's Verified badge is read, so a pasted centre link carries its real `isVerified` value. With Verified centres only on, a verified centre is kept and an unverified centre is dropped.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more leads data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>📇 <a href="https://apify.com/abotapi/truelocal-com-au-scraper"><b>TrueLocal AU Directory Listings &amp; Reviews Scraper</b></a><br>Scrape TrueLocal.com.au business listings by keyword, location, or URL. Extract names...</td><td>🏠 <a href="https://apify.com/abotapi/domain-com-au-scraper"><b>Domain.com.au</b></a><br>Extract enriched Domain.com.au property listings across buy, rent, and sold, with...</td></tr>
<tr><td>🚗 <a href="https://apify.com/abotapi/easyauto123-cars-scraper"><b>EasyAuto123 Scraper</b></a><br>Scrape EasyAuto123 vehicle listings into clean structured data. Extract prices, VINs...</td><td>🏠 <a href="https://apify.com/abotapi/homely-com-au-scraper"><b>Homely.com.au</b></a><br>Scrape Homely.com.au properties for sale, rent, and sold, plus agent finder, suburb...</td></tr>
<tr><td>🔌 <a href="https://apify.com/abotapi/appliancesonline-com-au-scraper"><b>Appliances Online Scraper</b></a><br>Scrape appliancesonline.com.au by category, keyword, or URL. Extract title, brand, AUD...</td><td>🏠 <a href="https://apify.com/abotapi/reiwa-com-au-scraper"><b>REIWA Scraper</b></a><br>Scrape REIWA.com.au across sale, rental, sold, commercial, business and rural properties...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/careforkids-com-au-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

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

Search mode = pick suburbs/postcodes + care types below. URL mode = paste any careforkids.com.au URL straight from a browser.

## `locations` (type: `array`):

One or more {suburb, postcode} pairs. Each pair becomes a SERP page on careforkids.com.au. Suburb names are slugified automatically ("Surry Hills" → "surry-hills"). Postcode is the 4-digit Australian postcode. Examples: {"suburb":"Sydney","postcode":"2000"} or {"suburb":"Melbourne","postcode":"3000"}. The postcode is optional: with a suburb name only, the postcode is looked up on the site (an unmatched name is logged as an error and skipped).

## `careTypes` (type: `array`):

Filter by childcare service type. Each (location × type) pair becomes a separate SERP fetch. Pick "all" to grab every service in a suburb in one fetch (covers all the types below). Default "all" returns every centre advertising any of the seven care types.

## `verifiedOnly` (type: `boolean`):

Drop centres not flagged as verified by careforkids.com.au. Applies in Search mode and to any pasted URL — a search results URL or a single centre URL.

## `vacanciesOnly` (type: `boolean`):

Drop centres that report no current vacancies. Applies in Search mode and to any pasted URL — a search results URL or a single centre URL.

## `minRating` (type: `integer`):

Drop centres rated below this 1-5 score. Centres with no rating are kept. Applies in Search mode and to any pasted URL — a search results URL or a single centre URL.

## `maxDailyFee` (type: `integer`):

Drop centres with an advertised average daily fee above this amount. Centres with no advertised fee are kept. Applies in Search mode and to any pasted URL — a search results URL or a single centre URL.

## `urls` (type: `array`):

One or more careforkids.com.au URLs. Examples: https://www.careforkids.com.au/child-care/sydney/2000 (all care types in Sydney CBD), https://www.careforkids.com.au/pre-school/sydney/2000 (pre-schools in Sydney CBD; other care-type prefixes work the same way), or a single centre detail URL like https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011. Multi-URL supported. Filter fields above (verifiedOnly, vacanciesOnly, minRating, maxDailyFee) still apply — including to a single pasted centre URL, not only a pasted search URL.

## `maxListings` (type: `integer`):

Stop after this many centres across all searches. 0 = no cap. Each suburb+postcode page returns roughly 5-50 centres (no pagination, single page exhausts the locality). Default 20 keeps runs bounded; raise it (or set 0) when scraping multiple suburbs.

## `fetchDetails` (type: `boolean`):

When ON, also fetch each centre's profile page for the full fee breakdown by age group, vacancy availability per day, NQS quality area ratings, gallery image URLs, contact name, contact hours, website + social links, service approval number, full feature list, and parent reviews. SERP cards already include name, address, GPS, phone, rating, average fee, vacancies, and abbreviated feature list, so simple feeds work fine with this OFF. Forced ON when Reviews-only output is enabled.

## `reviewsOnly` (type: `boolean`):

When ON, the dataset becomes one row per parent review (reviewer name, rating, date, full text, source, avatar) with centre context attached (centreId, centreName, suburb, postcode, state, GPS) instead of one row per centre. Pairs with either Search or URL mode.

## `maxReviewsPerCentre` (type: `integer`):

Caps how many reviews are returned per centre: it limits the Reviews-only rows AND the reviews embedded on detail rows and on pasted single-centre rows. Default 20; 0 or any value above 1000 uses the 1000 ceiling.

## `proxy` (type: `object`):

Optional proxy configuration. Leave the default unless you need to provide your own routing for repeated or high-volume runs.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large crawl of centres without returning or charging for centres already collected there. Use this after an interrupted run, or when continuing a suburb sweep in another run. For recurring monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or weekly monitoring. The first run returns all matching centres as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED centres. UPDATED means any returned field changed (fee, vacancies, ratings, review counts, fee tables, detail fields, etc.); the timestamp scrapedAt and the volatile raw.WaitlistUrl / raw.SpecialOfferImage are never compared, and you can exclude more fields with "Ignore fields when detecting changes". Turn on "Emit unchanged" or "Emit expired" only when you also want those centres returned (and billed). State is kept separately for each suburb/postcode/care-type/URL and filter/detail setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above. Off by default so existing scheduled runs are unaffected.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the locations/care types/URLs and filter/detail settings — different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return centres that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return centres that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search — not when Max listings capped it, when a search was unreachable, or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need this tracking.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Field names (matched at any depth, e.g. dailyFee, hasVacancies, reviewCount) that must NOT count as a change. A centre that differs only in these fields stays UNCHANGED and they are left out of changedFields. The fields are still returned in the output. Changing this list never causes a one-time wave of UPDATED rows. Already ignored automatically: scrapedAt and the volatile raw.WaitlistUrl / raw.SpecialOfferImage.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    {
      "suburb": "Sydney",
      "postcode": "2000"
    }
  ],
  "careTypes": [
    "all"
  ],
  "verifiedOnly": false,
  "vacanciesOnly": false,
  "urls": [
    "https://www.careforkids.com.au/child-care/sydney/2000",
    "https://www.careforkids.com.au/pre-school/sydney/2000",
    "https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011"
  ],
  "maxListings": 20,
  "fetchDetails": false,
  "reviewsOnly": false,
  "maxReviewsPerCentre": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `reviews` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (type: `string`):

No description

# 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": "search",
    "locations": [
        {
            "suburb": "Sydney",
            "postcode": "2000"
        }
    ],
    "urls": [
        "https://www.careforkids.com.au/child-care/sydney/2000",
        "https://www.careforkids.com.au/pre-school/sydney/2000",
        "https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011"
    ],
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/careforkids-com-au-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": "search",
    "locations": [{
            "suburb": "Sydney",
            "postcode": "2000",
        }],
    "urls": [
        "https://www.careforkids.com.au/child-care/sydney/2000",
        "https://www.careforkids.com.au/pre-school/sydney/2000",
        "https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011",
    ],
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/careforkids-com-au-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": "search",
  "locations": [
    {
      "suburb": "Sydney",
      "postcode": "2000"
    }
  ],
  "urls": [
    "https://www.careforkids.com.au/child-care/sydney/2000",
    "https://www.careforkids.com.au/pre-school/sydney/2000",
    "https://www.careforkids.com.au/child-care/k60qk/ku-phillip-park-childrens-centre-woolloomooloo-2011"
  ],
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false
}' |
apify call abotapi/careforkids-com-au-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/careforkids-com-au-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/lOGPlYbszMw6Rrwef/builds/bgIPAzqqdxfw3MF6X/openapi.json
