# School Holidays & Term Dates API: UK, Australia, Malaysia (`messnomore/school-holidays-api`) Actor

School term dates, half terms and school holidays by council, state or region for the UK, Australia and Malaysia as clean JSON. Official government sources, a source link and last-verified date on every record, checked weekly.

- **URL**: https://apify.com/messnomore/school-holidays-api.md
- **Developed by:** [Wong Xian Qi](https://apify.com/messnomore) (community)
- **Categories:** Travel, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 school holiday records

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

### What does School Holidays & Term Dates API do?

**School Holidays & Term Dates API** gives you school term dates, half terms and school holidays for UK councils,
Australian states and Malaysian states as clean, consistent JSON. Every record links to the official government page,
PDF or calendar feed it comes from and carries a `lastVerified` date, so you can show it to customers and trust it.
Each source is checked every week, and changes are reviewed before they are published.

Use it in Apify Console with no code, or as a **school holidays API** from your own website, app, spreadsheet or
pricing engine.

### Why use School Holidays & Term Dates API?

Every council, state and ministry publishes its school calendar differently: HTML tables, PDFs, calendar feeds,
six-term or four-term years, Malay-language tables. Collecting them by hand every year is slow and error-prone. This
Actor does it for you:

- 📅 **One format for every country**: terms, half terms and holidays with ISO dates, the school year, the number of
  days and the name of each period.
- 🔗 **Source on every record**: `sourceUrl`, `sourceName`, `licence` and `lastVerified` for each date range.
- ✅ **Checked, not just scraped**: dates are extracted twice and compared, weekday names are checked against the
  dates, and every change is reviewed before it goes live.
- 🧭 **Region names you already use**: "East Sussex County Council", `GB-ESX`, "NSW" or "Penang" all work.
- 🏦 **Bank holidays included on request**: UK bank holidays for England and Wales, Scotland and Northern Ireland,
  mapped onto the same school years.
- 🤖 **Apify platform features**: run it on a schedule, call it by API, or send the results to Google Sheets, Slack,
  Make or Zapier with [integrations](https://docs.apify.com/platform/integrations).

Who uses it: **travel and holiday companies** (school holiday demand and pricing), **childcare, holiday clubs and
activity camps**, **family and education apps**, **HR and workforce planners**, and **marketers** timing
back-to-school campaigns.

### Which countries and regions are covered?

| Country                | Regions                                                                                                                                                                                                               |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 🇬🇧 United Kingdom (GB) | England: Buckinghamshire, Bracknell Forest, East Sussex, Milton Keynes, Staffordshire, Wolverhampton. Wales: Merthyr Tydfil, Monmouthshire. Scotland: Falkirk, Renfrewshire. Northern Ireland (school holidays only). |
| 🇦🇺 Australia (AU)      | New South Wales (Eastern and Western divisions), Victoria, Queensland, Western Australia, Tasmania.                                                                                                                   |
| 🇲🇾 Malaysia (MY)       | All 13 states and 3 federal territories (Kumpulan A and Kumpulan B calendars, with the Kedah and Sarawak variations).                                                                                                 |

More UK councils will be added. Only sources whose terms allow reuse are included. Every UK source is published under
the Open Government Licence, and every Australian source under CC BY 4.0.

### What data does School Holidays & Term Dates API return?

| Field          | Description                                                                               |
| -------------- | ----------------------------------------------------------------------------------------- |
| `country`      | `GB`, `AU` or `MY`.                                                                       |
| `region`       | Council, state or territory name.                                                         |
| `regionCode`   | Stable code, ISO 3166-2 where one exists (`GB-ESX`, `AU-NSW`, `MY-10`).                   |
| `schoolYear`   | `2026/27` in the UK, `2026` in Australia and Malaysia.                                    |
| `type`         | `term`, `half_term`, `holiday` or `public_holiday`.                                       |
| `name`         | Name of the period, e.g. "Autumn term", "October half term", "Christmas holiday".         |
| `start`, `end` | First and last day, inclusive, `YYYY-MM-DD`.                                              |
| `days`         | Calendar days from start to end.                                                          |
| `derived`      | `true` when the holiday was worked out from the term dates (the source lists only terms). |
| `notes`        | Anything you should know, e.g. "Merged from Term 1 and Term 2".                           |
| `scope`        | Which schools the dates apply to.                                                         |
| `sourceName`   | Publisher of the official source.                                                         |
| `sourceUrl`    | Official page, PDF or calendar feed.                                                      |
| `licence`      | Licence of the source data.                                                               |
| `lastVerified` | Last day the source was checked and still matched these dates.                            |

### How to get school term dates with School Holidays & Term Dates API

1. Click **Try for free** and open the **Input** tab.
2. Choose the **Country**.
3. Add the councils or states you need under **Regions**, or leave it empty for all of them.
4. Optionally pick **School years** and **Record types**, and set **Maximum results**.
5. Click **Start**. Results appear in the **Output** tab within seconds; download them as JSON, CSV or Excel.

### How much does it cost to get school holiday dates?

This Actor uses **pay-per-event pricing**: you pay **$0.005 per record returned**, plus a start fee of $0.00005 per
run. There is no charge for compute time.

- One UK council for two school years is about 18 records: **about $0.09**.
- All six Australian regions for one school year is about 45 to 55 records: **about $0.25**.
- All 16 Malaysian states and territories for one year is about 160 to 190 records: **about $0.80 to $0.95**.
- **Maximum results** is a hard cap, and Apify also stops charging when your run reaches the maximum cost you set.
- Invalid input or unavailable data stops the run before any record is saved, so you pay no record fees. Records saved before an unexpected failure or an abort stay charged.

Apify's free plan includes monthly platform credit, which is enough for many runs.

### Input

See the **Input** tab for every option. Example input:

```json
{
    "country": "GB",
    "regions": ["East Sussex", "Falkirk"],
    "years": [2026, 2027],
    "types": ["term", "half_term", "holiday"],
    "includeDerived": true,
    "maxResults": 1000
}
```

- **regions**: names, codes or common short names. Words such as "Council", "County" and "City of" are ignored. A
  region that is not covered is reported in the run status and in the `SUMMARY` record; the others are still returned.
- **years**: the year each school year starts. In the UK `2026` means 2026/27; in Australia and Malaysia it means the
  2026 school year. Leave it empty for the current school year, every later year already published, and holidays
  still running today.
- **types**: add `public_holiday` to get bank holidays too (UK only for now).

### Output

You can download the dataset in various formats such as **JSON, HTML, CSV or Excel**. Example results from the input
above:

```json
[
    {
        "country": "GB",
        "region": "East Sussex",
        "regionCode": "GB-ESX",
        "scope": "Community and voluntary-controlled schools. Academies, free and foundation schools may differ.",
        "schoolYear": "2026/27",
        "type": "term",
        "name": "Autumn term",
        "start": "2026-09-02",
        "end": "2026-12-18",
        "days": 108,
        "derived": false,
        "notes": "Merged from Term 1 (2 September to 23 October 2026) and Term 2 (2 November to 18 December 2026).",
        "sourceName": "East Sussex County Council",
        "sourceUrl": "https://www.eastsussex.gov.uk/education-learning/term-dates",
        "licence": "Open Government Licence v3.0",
        "lastVerified": "2026-10-12"
    },
    {
        "country": "GB",
        "region": "East Sussex",
        "regionCode": "GB-ESX",
        "scope": "Community and voluntary-controlled schools. Academies, free and foundation schools may differ.",
        "schoolYear": "2026/27",
        "type": "half_term",
        "name": "October half term",
        "start": "2026-10-24",
        "end": "2026-11-01",
        "days": 9,
        "derived": false,
        "notes": null,
        "sourceName": "East Sussex County Council",
        "sourceUrl": "https://www.eastsussex.gov.uk/education-learning/term-dates",
        "licence": "Open Government Licence v3.0",
        "lastVerified": "2026-10-12"
    }
]
```

The run also saves a `SUMMARY` record with the regions matched and not covered, the number of records matched and
returned, and when the data was last checked.

### Use School Holidays & Term Dates API as an API

```bash
curl -X POST "https://api.apify.com/v2/acts/messnomore~school-holidays-api/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"country": "AU", "regions": ["NSW", "VIC"], "years": [2027]}'
```

See the **API** tab for clients in JavaScript and Python. You can also run it from AI assistants through the
[Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

### Tips for better results

- Keep a copy of the results and re-run once a month or on a schedule: `lastVerified` shows when each source was
  last confirmed.
- Turn off **Include derived holidays** if you only want periods the publisher lists itself.
- Need several countries? Run the Actor once per country; each run takes a few seconds.

### Related guides

- [Is there an API for school term dates and school holidays?](https://wong13977-oss.github.io/school-term-dates-api/)
- [Free school term dates sample dataset on GitHub](https://github.com/wong13977-oss/school-term-dates): 2026 NSW, Victoria and Queensland and 2026/27 Buckinghamshire, Staffordshire and Falkirk as JSON and CSV (CC BY 4.0 / OGL v3.0).

### FAQ

#### Where do the dates come from, and how are they checked?

From the official publishers only: UK councils and the Northern Ireland Department of Education, the education
departments of the Australian states, and Malaysia's Ministry of Education (KPM). The pages and PDFs are read with AI
twice, independently, and each date range read from a document must come with a quote from it. Both readings are compared and
checked automatically: valid dates, no overlapping terms, half terms inside terms, the expected number of terms per
year, and weekday names that match the dates. Every change then waits for approval before it is published.

#### How fresh is the data?

Every source is checked weekly. `lastVerified` on each record is the last day its source was fetched and still
matched the dates. New school years appear once the publisher releases them.

#### Which region names and codes can I use?

Names, codes and the short names in brackets all work, in any letter case:

- **GB**: Buckinghamshire `GB-BKM` (Bucks), Bracknell Forest `GB-BRC` (Bracknell), East Sussex `GB-ESX`, Milton
  Keynes `GB-MIK` (MK), Staffordshire `GB-STS` (Staffs), Wolverhampton `GB-WLV`, Merthyr Tydfil `GB-MTY` (Merthyr),
  Monmouthshire `GB-MON` (Sir Fynwy), Falkirk `GB-FAL`, Renfrewshire `GB-RFW`, Northern Ireland `GB-NIR` (NI).
- **AU**: New South Wales `AU-NSW` (NSW, Eastern division dates), New South Wales Western division `AU-NSW-W` (NSW
  Western), Victoria `AU-VIC` (VIC), Queensland `AU-QLD` (QLD), Western Australia `AU-WA` (WA), Tasmania `AU-TAS`
  (TAS).
- **MY**: Johor `MY-01`, Kedah `MY-02`, Kelantan `MY-03`, Melaka `MY-04` (Malacca), Negeri Sembilan `MY-05`, Pahang
  `MY-06`, Pulau Pinang `MY-07` (Penang), Perak `MY-08`, Perlis `MY-09`, Selangor `MY-10`, Terengganu `MY-11`, Sabah
  `MY-12`, Sarawak `MY-13`, Kuala Lumpur `MY-14` (KL), Labuan `MY-15`, Putrajaya `MY-16`.

#### Why are some holidays marked `derived`?

Some publishers (for example Wolverhampton, Merthyr Tydfil, Monmouthshire, Victoria and Western Australia) list only
term dates, or give only the first day of the summer holiday. The holidays between their terms are then worked out
from the term dates, marked `derived: true` and given a note. Turn off **Include derived holidays** to leave them out.

#### Do the dates apply to every school?

They apply to the schools named in `scope`: in England, community and voluntary-controlled schools; academies, free
and foundation schools may set their own dates. Training (INSET) days are set by each school and are not included.
Northern Ireland publishes school holidays but not term dates, so only holidays are returned for it. Falkirk has four
terms per school year, and the data keeps them as four.

#### Are public holidays included?

Add `public_holiday` to **Record types** to get UK bank holidays for England and Wales, Scotland or Northern Ireland
(from GOV.UK), mapped onto the school year of the region. Public holidays for Australia and Malaysia are not included
yet. For Malaysia, the `holiday` records include the extra festive school holidays announced by KPM.

#### Why did I get fewer records than I expected?

A region may not be covered yet (it is listed in the run status and `SUMMARY`), the school year may not be published
yet, or the run reached **Maximum results** or your maximum cost per run.

#### Can I use the data commercially?

The UK data is published under the Open Government Licence v3.0 and the Australian data under CC BY 4.0, both of
which allow commercial use with attribution. Keep `sourceName`, `sourceUrl` and `licence` with the data and show an
attribution such as "Contains public sector information licensed under the Open Government Licence v3.0". The
Malaysian dates are factual dates from KPM's official academic calendar; credit KPM as the source.

#### Is my input stored or shared?

No. Your input is used only to filter the dates. Like every Apify run, it stays in your own run storage, which you can
delete at any time.

#### I found wrong or missing data. What can I do?

Open the **Issues** tab and include the region and the date range. Requests for new councils, states or countries are
welcome there too.

# Actor input Schema

## `country` (type: `string`):

Country of the school calendars.

## `regions` (type: `array`):

Councils (UK), states or territories (Australia, Malaysia), by name or code: e.g. "East Sussex", "GB-FAL", "Northern Ireland", "NSW", "Victoria", "Selangor". Words like "County Council" are ignored. Leave empty for every covered region of the country. See the README for the full list.

## `years` (type: `array`):

Start year of each school year you need, e.g. \[2026, 2027]. In the UK, 2026 means the 2026/27 school year (September or August to July); in Australia and Malaysia it is the 2026 school year. Up to 10 years. Leave empty for the current school year, every later year already published, and holidays still running today.

## `types` (type: `array`):

Which periods to return. Terms are the school terms, half terms the short breaks inside a term, holidays the breaks between terms (and short closures for all pupils). Public holidays are the official bank holidays (UK only for now), mapped onto the same school years.

## `includeDerived` (type: `boolean`):

Some publishers list only term dates. The holidays between their terms are then worked out from the term dates and marked "derived": true. Turn this off to get only periods the source states itself.

## `maxResults` (type: `integer`):

Upper limit on returned records. You pay per returned record, so this also caps the cost of a run.

## Actor input object example

```json
{
  "country": "GB",
  "regions": [
    "East Sussex",
    "Falkirk"
  ],
  "years": [
    2026,
    2027
  ],
  "types": [
    "term",
    "half_term",
    "holiday"
  ],
  "includeDerived": true,
  "maxResults": 1000
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "regions": [
        "East Sussex",
        "Falkirk"
    ],
    "years": [
        2026,
        2027
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("messnomore/school-holidays-api").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 = {
    "regions": [
        "East Sussex",
        "Falkirk",
    ],
    "years": [
        2026,
        2027,
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("messnomore/school-holidays-api").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 '{
  "regions": [
    "East Sussex",
    "Falkirk"
  ],
  "years": [
    2026,
    2027
  ]
}' |
apify call messnomore/school-holidays-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,messnomore/school-holidays-api"
        }
    }
}
```

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/y73mkEBegpydAMjnG/builds/Pk54iexNdwvOhpeX5/openapi.json
