# SEEK Job Scraper (AU & NZ) (`corvuslab/seek-scraper`) Actor

Scrape job listings from SEEK (seek.com.au & seek.co.nz) by keyword, location, category and more.

- **URL**: https://apify.com/corvuslab/seek-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## 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.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## SEEK Job Scraper — Australia & New Zealand 🇦🇺 🇳🇿

Extract job listings from **SEEK** ([seek.com.au](https://www.seek.com.au) and
[seek.co.nz](https://www.seek.co.nz)) by keyword, location, category, work type,
date or salary — with structured salary data, full descriptions, company
profiles, incremental change tracking and built-in notifications.

Great for salary and market research, recruitment intelligence, competitor
monitoring, and feeding structured job data into dashboards or AI agents.

### Key features

- 🌏 **Two-market coverage** — one actor scrapes both SEEK Australia and New Zealand.
- 🔍 **Keyword & batch search** — one query or many in a single run, deduplicated by job ID.
- 🎯 **Rich filters** — location, classification/sub-classification, work type,
  work arrangement (on-site/hybrid/remote), "listed in last N days", salary range,
  and sort by relevance or date.
- 💰 **Structured salary** — `salaryText` parsed into `salaryMin` / `salaryMax` /
  `salaryCurrency` / `salaryType` automatically.
- 📄 **Detail enrichment** — full description as plain text, HTML **and** Markdown,
  plus the company profile.
- 🔁 **Incremental mode** — on recurring runs, emit and charge for only NEW /
  UPDATED / REAPPEARED / EXPIRED jobs. Saves heavily on daily monitoring (see below).
- ♻️ **Repost detection** — flag or drop jobs re-listed under a new ID.
- 🧮 **Post-filters** — keyword include/exclude, date windows, and custom field rules.
- 🔔 **Notifications** — push matching jobs to Telegram, Slack, Discord or a
  generic JSON webhook when a run finishes.
- 🧰 **AI-friendly output** — `compact` mode and `excludeEmptyFields` for lean records.
- 🔗 **Start URLs** — paste any SEEK search or job URL straight from your browser.

### Input

| Field | Type | Description |
|---|---|---|
| `query` | string | Keywords, e.g. `"python"`. Leave blank to browse all jobs. |
| `queries` | array | Multiple keyword searches in one run. |
| `country` | enum | `AU` (default) or `NZ`. |
| `startUrls` | array | SEEK search-results or `/job/<id>` URLs. |
| `location` | string | e.g. `"Sydney NSW"`, `"Auckland"`. |
| `classification` / `subClassification` | string | SEEK category IDs (e.g. `6281` = ICT). |
| `workType` | array | `fullTime`, `partTime`, `contract`, `casual`. |
| `workArrangement` | array | `onsite`, `hybrid`, `remote`. |
| `dateRange` | enum | `1`, `3`, `7`, `14`, `31` days. |
| `sortMode` | enum | `relevance` (default) or `date`. |
| `salaryMin` / `salaryMax` | integer | Salary range in local currency (set both). |
| `includeKeywords` / `excludeKeywords` | array | Keep jobs matching an include term; drop jobs matching an exclude term. |
| `keywordMatch*` | boolean | Limit keyword matching to title/company/description/category/bulletPoints. None on = all fields. |
| `fromDate` / `toDate` | string | Keep jobs posted within this date window (YYYY-MM-DD; `toDate` inclusive). |
| `maxAgeMinutes` | integer | Keep only jobs posted within N minutes before the run. |
| `customFilters` | array | Rule-based filters on any output field, e.g. `[{"field":"salaryMin","operator":"gte","value":100000}]`. Operators: includes, notIncludes, equals, notEquals, gt, gte, lt, lte. |
| `maxResults` | integer | Max jobs per query (0 = unlimited, capped at 5000). Default 50. |
| `maxPages` | integer | Max search pages per query. Default 25. |
| `includeDetails` | boolean | Fetch each job's detail page. Default `true`. |
| `descriptionMaxLength` | integer | Truncate description text (0 = no limit). |
| `descriptionFormat` | enum | `all`, `text`, `html`, `markdown`. |
| `incrementalMode` | boolean | Track changes across runs; emit only NEW/UPDATED/REAPPEARED by default. |
| `stateKey` | string | Stable name for the tracking state (auto-derived if blank). |
| `emitUnchanged` / `emitExpired` | boolean | Also emit UNCHANGED / EXPIRED jobs. |
| `skipReposts` | boolean | Detect and drop reposts; kept jobs are tagged `isRepost`/`repostOfId`. |
| `telegramToken` + `telegramChatId` | string | Notify Telegram (BotFather token + chat ID). |
| `slackWebhookUrl` / `discordWebhookUrl` | string | Notify a Slack / Discord incoming webhook. |
| `webhookUrl` + `webhookHeaders` | string / object | POST structured JSON to any endpoint, with optional custom headers. |
| `notificationLimit` | integer | Max jobs listed per message (default 5; total is still reported). |
| `notifyOnlyChanges` | boolean | Only notify about NEW/UPDATED/REAPPEARED jobs (needs incremental mode). |
| `includeRunSummary` | boolean | Prepend a one-line summary to each notification (default true). |
| `compact` | boolean | Core fields only. |
| `excludeEmptyFields` | boolean | Drop null/empty fields. |

#### Example input

```json
{
    "query": "registered nurse",
    "country": "NZ",
    "location": "Auckland",
    "dateRange": "7",
    "sortMode": "date",
    "maxResults": 100,
    "includeDetails": true
}
````

### Output

Each job is pushed to the run's default dataset. Example record (abridged):

```json
{
    "jobId": "92981016",
    "title": "Registered Nurse - Dermatology and Skin Cancer",
    "company": "Skintel Limited",
    "location": "Rosedale, Auckland",
    "locationCountry": "NZ",
    "salaryText": "$40 – $50 per hour",
    "salaryMin": 40,
    "salaryMax": 50,
    "salaryCurrency": "NZD",
    "salaryType": "hourly",
    "workType": "Full time",
    "workArrangement": "On-site",
    "category": "Healthcare & Medical",
    "subCategory": "Nursing - General Medical & Surgical",
    "teaser": "Join a leading skin cancer and dermatology clinic!",
    "url": "https://www.seek.co.nz/job/92981016",
    "isSponsored": false,
    "postedDate": "2026-06-26T22:46:48.331Z",
    "searchQuery": "registered nurse",
    "sourceCountry": "NZ",
    "scrapedAt": "2026-06-30T13:00:00+00:00",
    "description": "…",
    "descriptionMarkdown": "…"
}
```

In **compact** mode only `jobId`, `title`, `company`, `location`, `salaryText`,
`workType`, `postedDate`, `url`, `applyUrl` and `searchQuery` are returned.

#### Incremental fields

When `incrementalMode` is on, every record also carries:

- `changeType` — `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`
- `firstSeenAt` / `lastSeenAt` — when the job was first and most recently seen
- `isRepost` / `repostOfId` — set when repost detection matches an earlier listing

### Incremental mode & monitoring savings

Running on a schedule? Turn on `incrementalMode`. The **first run builds a
baseline**; every run after that emits — and charges for — **only the jobs that
changed**. Unchanged jobs are recognised before their detail page is even fetched,
so you skip both the work and the cost.

Because this actor is pay-per-result, your cost after the baseline scales with how
much the market actually changes ("churn"), not with the total number of listings
you monitor:

| Daily churn | Records emitted per run (after baseline) | Approx. saving vs a full re-scrape |
|---|---|---|
| 5% (stable niche) | ~5% | ~90% |
| 15% (moderate) | ~15% | ~80% |
| 30% (fast-moving) | ~30% | ~65% |

These figures apply to the per-result portion of the cost over a month of daily
runs; the exact amount depends on the price configured for this actor. Set
`emitExpired` to also receive listings that have dropped off, and `emitUnchanged`
if you want the full set every run.

Keep `maxResults` / `maxPages` consistent between scheduled runs — they define the
set of jobs being tracked.

### Notifications

Get alerted the moment matching jobs appear. Fill in only the channels you want;
each fires independently when a run finishes and there are matching jobs.

- ✈️ **Telegram** — `telegramToken` (from @BotFather) + `telegramChatId`.
- 💬 **Slack** — `slackWebhookUrl` (Incoming Webhook).
- 🎮 **Discord** — `discordWebhookUrl` (channel webhook).
- 🪝 **Generic webhook** — `webhookUrl` receives a structured JSON payload
  (run metadata + a `jobs` array) with optional `webhookHeaders`. Ideal for
  n8n / Make / Zapier.

Pair with `incrementalMode` + `notifyOnlyChanges` to be alerted only about
NEW/UPDATED/REAPPEARED jobs on scheduled runs. Credentials are stored encrypted.

### Use cases

- Salary and market research across AU & NZ.
- Track salary trends and hiring demand over time.
- Monitor new and changed listings on a schedule without re-processing everything.
- Build recruitment and outreach lists from company and role data.
- Feed structured job data into dashboards, data warehouses or AI agents.

### Pricing

This actor uses **pay-per-event** pricing: a small per-run start fee plus a small
fee per job record. You only pay for the jobs you actually receive — and with
incremental mode on, only for the ones that changed.

### FAQ

**Do I need a SEEK account or login?** No. The actor reads SEEK's public job
listings; no credentials are required.

**Can I scrape both Australia and New Zealand?** Yes — set `country` to `AU` or
`NZ` (run once per market, or use `startUrls` from either site).

**Why are some company fields empty?** `companyUrl` and `companyDescription` are
only available for advertisers that have a SEEK company profile.

**Is it legal to scrape seek.com.au / seek.co.nz?** This actor extracts publicly
available data from SEEK. Web scraping of public information is generally
considered legal, but you should always review the target site's terms of service
and ensure your use case complies with applicable laws and regulations, including
GDPR where relevant.

***

*This is an unofficial actor and is not affiliated with, endorsed by, or connected
to SEEK. "SEEK" is a trademark of its respective owner and is used here only to
describe the site this actor works with.*

# Actor input Schema

## `query` (type: `string`):

Keywords to search for, e.g. "python" or "registered nurse". Leave blank to browse all jobs in the chosen country/location.

## `queries` (type: `array`):

Run several keyword searches in one run. Results are deduplicated by job ID across all queries.

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

Which SEEK market to search: Australia (seek.com.au) or New Zealand (seek.co.nz).

## `startUrls` (type: `array`):

Optional: paste SEEK search-results URLs or single job-detail URLs straight from your browser. Used in addition to the keyword search above.

## `location` (type: `string`):

Optional location to filter by, e.g. "Sydney NSW", "Melbourne VIC", "Auckland". Leave blank to search the whole country.

## `classification` (type: `string`):

Optional SEEK job-category ID. Examples: 6281 = Information & Communication Technology, 6317 = Healthcare & Medical, 6164 = Engineering. Find IDs in the URL when you pick a category on SEEK.

## `subClassification` (type: `string`):

Optional SEEK sub-category ID. Requires a parent Classification ID.

## `workType` (type: `array`):

Filter by employment type. Select one or more; leave empty for any.

## `workArrangement` (type: `array`):

Filter by where the work is done. Select one or more; leave empty for any.

## `dateRange` (type: `string`):

Only include jobs listed within this period. Leave empty for any time.

## `sortMode` (type: `string`):

Order results by SEEK relevance or by listing date (newest first).

## `salaryMin` (type: `integer`):

Optional minimum salary in local currency (AUD/NZD). Requires Maximum salary to be set as well.

## `salaryMax` (type: `integer`):

Optional maximum salary in local currency (AUD/NZD). Requires Minimum salary to be set as well.

## `includeKeywords` (type: `array`):

Keep only jobs that contain at least one of these terms. Leave empty to keep all.

## `excludeKeywords` (type: `array`):

Drop any job that contains one of these terms.

## `keywordMatchTitle` (type: `boolean`):

Match keywords against the job title. If none of these 'Match in …' toggles are on, keywords are matched across all fields.

## `keywordMatchCompany` (type: `boolean`):

Match keywords against the company name.

## `keywordMatchDescription` (type: `boolean`):

Match keywords against the job teaser/summary.

## `keywordMatchCategory` (type: `boolean`):

Match keywords against the job category and sub-category.

## `keywordMatchBulletPoints` (type: `boolean`):

Match keywords against the job's key bullet points.

## `fromDate` (type: `string`):

Keep only jobs posted on or after this date (YYYY-MM-DD).

## `toDate` (type: `string`):

Keep only jobs posted on or before this date (YYYY-MM-DD, inclusive).

## `maxAgeMinutes` (type: `integer`):

Keep only jobs posted within this many minutes before the run. Handy for frequent monitoring runs.

## `customFilters` (type: `array`):

Advanced rules applied to output fields. Each rule is {"field": "<output field>", "operator": "<op>", "value": <value>}. Operators: includes, notIncludes, equals, notEquals, gt, gte, lt, lte. All rules must pass (AND). Example: \[{"field":"salaryMin","operator":"gte","value":100000}]

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

Maximum number of jobs to return per query. Use 0 for unlimited (hard-capped at 5000).

## `maxPages` (type: `integer`):

Maximum number of search-result pages to fetch per query (a safety cap on cost). SEEK returns roughly 22 organic jobs per page.

## `includeDetails` (type: `boolean`):

Open each job's detail page to add the full description, company profile and salary. Slower and uses more requests.

## `descriptionMaxLength` (type: `integer`):

Truncate the description text to this many characters. Use 0 for no limit. Only applies when 'Include job details' is enabled.

## `descriptionFormat` (type: `string`):

Which description representations to include (only with 'Include job details'): all, plain text, HTML, or Markdown.

## `compact` (type: `boolean`):

Return only core fields (title, company, location, salary, dates, URLs) — handy for AI/agent workflows.

## `excludeEmptyFields` (type: `boolean`):

Remove fields that are null or empty from each output record.

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

Classify each job as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED against the previous run and, by default, emit only NEW/UPDATED/REAPPEARED.

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

Optional stable name for the tracking state so separate schedules don't clash. Leave blank to derive it automatically from the search parameters.

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

Also output jobs that haven't changed since the last run.

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

Also output jobs that were tracked before but have now disappeared from the search (changeType = EXPIRED).

## `skipReposts` (type: `boolean`):

Detect and drop reposts — the same job (same company, title and location) re-listed under a new ID. Cross-run detection uses incremental state; kept jobs are tagged with isRepost / repostOfId.

## `telegramToken` (type: `string`):

Bot token from @BotFather. Leave blank to skip Telegram.

## `telegramChatId` (type: `string`):

Chat or channel ID to send to (e.g. from @userinfobot). Required with the bot token.

## `slackWebhookUrl` (type: `string`):

Slack Incoming Webhook URL (https://hooks.slack.com/services/...). Leave blank to skip Slack.

## `discordWebhookUrl` (type: `string`):

Discord channel webhook URL. Leave blank to skip Discord.

## `webhookUrl` (type: `string`):

POST a structured JSON payload (run metadata + job records) here — handy for n8n, Make or Zapier. Leave blank to skip.

## `webhookHeaders` (type: `object`):

Optional custom HTTP headers for the generic webhook, e.g. {"Authorization": "Bearer ..."}.

## `notificationLimit` (type: `integer`):

How many jobs to list in the message (the message also reports the total matched).

## `notifyOnlyChanges` (type: `boolean`):

Only notify about NEW/UPDATED/REAPPEARED jobs. Requires Incremental mode; ignored otherwise.

## `includeRunSummary` (type: `boolean`):

Prepend a one-line summary (country, match count, query) to each notification.

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

How many requests to run in parallel. The actor uses geo-targeted residential proxies automatically, so raising this mainly trades speed for cost.

## Actor input object example

```json
{
  "query": "python",
  "country": "AU",
  "sortMode": "relevance",
  "keywordMatchTitle": false,
  "keywordMatchCompany": false,
  "keywordMatchDescription": false,
  "keywordMatchCategory": false,
  "keywordMatchBulletPoints": false,
  "maxResults": 50,
  "maxPages": 25,
  "includeDetails": true,
  "descriptionMaxLength": 0,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "skipReposts": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false,
  "includeRunSummary": true,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `jobs` (type: `string`):

All scraped job listings as JSON (the run's default dataset).

## `jobsOverview` (type: `string`):

Job listings limited to the key columns from the Overview view.

# 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 = {
    "query": "python"
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/seek-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 = { "query": "python" }

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/seek-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "query": "python"
}' |
apify call corvuslab/seek-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=corvuslab/seek-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SEEK Job Scraper (AU & NZ)",
        "description": "Scrape job listings from SEEK (seek.com.au & seek.co.nz) by keyword, location, category and more.",
        "version": "1.0",
        "x-build-id": "XuOtBn5eO1BdAOmeR"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/corvuslab~seek-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-corvuslab-seek-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/corvuslab~seek-scraper/runs": {
            "post": {
                "operationId": "runs-sync-corvuslab-seek-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/corvuslab~seek-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-corvuslab-seek-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "query": {
                        "title": "Search query 🔍",
                        "type": "string",
                        "description": "Keywords to search for, e.g. \"python\" or \"registered nurse\". Leave blank to browse all jobs in the chosen country/location."
                    },
                    "queries": {
                        "title": "Search queries 📑",
                        "type": "array",
                        "description": "Run several keyword searches in one run. Results are deduplicated by job ID across all queries.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "Country 🌏",
                        "enum": [
                            "AU",
                            "NZ"
                        ],
                        "type": "string",
                        "description": "Which SEEK market to search: Australia (seek.com.au) or New Zealand (seek.co.nz).",
                        "default": "AU"
                    },
                    "startUrls": {
                        "title": "Start URLs 🔗",
                        "type": "array",
                        "description": "Optional: paste SEEK search-results URLs or single job-detail URLs straight from your browser. Used in addition to the keyword search above.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location 📍",
                        "type": "string",
                        "description": "Optional location to filter by, e.g. \"Sydney NSW\", \"Melbourne VIC\", \"Auckland\". Leave blank to search the whole country."
                    },
                    "classification": {
                        "title": "Classification ID 🗂️",
                        "type": "string",
                        "description": "Optional SEEK job-category ID. Examples: 6281 = Information & Communication Technology, 6317 = Healthcare & Medical, 6164 = Engineering. Find IDs in the URL when you pick a category on SEEK."
                    },
                    "subClassification": {
                        "title": "Sub-classification ID 🗂️",
                        "type": "string",
                        "description": "Optional SEEK sub-category ID. Requires a parent Classification ID."
                    },
                    "workType": {
                        "title": "Work type 💼",
                        "type": "array",
                        "description": "Filter by employment type. Select one or more; leave empty for any.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "fullTime",
                                "partTime",
                                "contract",
                                "casual"
                            ],
                            "enumTitles": [
                                "Full time",
                                "Part time",
                                "Contract/Temp",
                                "Casual/Vacation"
                            ]
                        }
                    },
                    "workArrangement": {
                        "title": "Work arrangement 🏠",
                        "type": "array",
                        "description": "Filter by where the work is done. Select one or more; leave empty for any.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "onsite",
                                "hybrid",
                                "remote"
                            ],
                            "enumTitles": [
                                "On-site",
                                "Hybrid",
                                "Remote"
                            ]
                        }
                    },
                    "dateRange": {
                        "title": "Listed in last 🗓️",
                        "enum": [
                            "1",
                            "3",
                            "7",
                            "14",
                            "31"
                        ],
                        "type": "string",
                        "description": "Only include jobs listed within this period. Leave empty for any time."
                    },
                    "sortMode": {
                        "title": "Sort by ↕️",
                        "enum": [
                            "relevance",
                            "date"
                        ],
                        "type": "string",
                        "description": "Order results by SEEK relevance or by listing date (newest first).",
                        "default": "relevance"
                    },
                    "salaryMin": {
                        "title": "Minimum salary 💰",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Optional minimum salary in local currency (AUD/NZD). Requires Maximum salary to be set as well."
                    },
                    "salaryMax": {
                        "title": "Maximum salary 💰",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Optional maximum salary in local currency (AUD/NZD). Requires Minimum salary to be set as well."
                    },
                    "includeKeywords": {
                        "title": "Include keywords ✅",
                        "type": "array",
                        "description": "Keep only jobs that contain at least one of these terms. Leave empty to keep all.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "excludeKeywords": {
                        "title": "Exclude keywords 🚫",
                        "type": "array",
                        "description": "Drop any job that contains one of these terms.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keywordMatchTitle": {
                        "title": "Match in title",
                        "type": "boolean",
                        "description": "Match keywords against the job title. If none of these 'Match in …' toggles are on, keywords are matched across all fields.",
                        "default": false
                    },
                    "keywordMatchCompany": {
                        "title": "Match in company",
                        "type": "boolean",
                        "description": "Match keywords against the company name.",
                        "default": false
                    },
                    "keywordMatchDescription": {
                        "title": "Match in description",
                        "type": "boolean",
                        "description": "Match keywords against the job teaser/summary.",
                        "default": false
                    },
                    "keywordMatchCategory": {
                        "title": "Match in category",
                        "type": "boolean",
                        "description": "Match keywords against the job category and sub-category.",
                        "default": false
                    },
                    "keywordMatchBulletPoints": {
                        "title": "Match in bullet points",
                        "type": "boolean",
                        "description": "Match keywords against the job's key bullet points.",
                        "default": false
                    },
                    "fromDate": {
                        "title": "Posted from date 📅",
                        "type": "string",
                        "description": "Keep only jobs posted on or after this date (YYYY-MM-DD)."
                    },
                    "toDate": {
                        "title": "Posted to date 📅",
                        "type": "string",
                        "description": "Keep only jobs posted on or before this date (YYYY-MM-DD, inclusive)."
                    },
                    "maxAgeMinutes": {
                        "title": "Max age (minutes) ⏱️",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Keep only jobs posted within this many minutes before the run. Handy for frequent monitoring runs."
                    },
                    "customFilters": {
                        "title": "Custom filters 🧩",
                        "type": "array",
                        "description": "Advanced rules applied to output fields. Each rule is {\"field\": \"<output field>\", \"operator\": \"<op>\", \"value\": <value>}. Operators: includes, notIncludes, equals, notEquals, gt, gte, lt, lte. All rules must pass (AND). Example: [{\"field\":\"salaryMin\",\"operator\":\"gte\",\"value\":100000}]"
                    },
                    "maxResults": {
                        "title": "Max results per query 🔢",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of jobs to return per query. Use 0 for unlimited (hard-capped at 5000).",
                        "default": 50
                    },
                    "maxPages": {
                        "title": "Max pages per query 📄",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of search-result pages to fetch per query (a safety cap on cost). SEEK returns roughly 22 organic jobs per page.",
                        "default": 25
                    },
                    "includeDetails": {
                        "title": "Include job details 📄",
                        "type": "boolean",
                        "description": "Open each job's detail page to add the full description, company profile and salary. Slower and uses more requests.",
                        "default": true
                    },
                    "descriptionMaxLength": {
                        "title": "Description max length ✂️",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Truncate the description text to this many characters. Use 0 for no limit. Only applies when 'Include job details' is enabled.",
                        "default": 0
                    },
                    "descriptionFormat": {
                        "title": "Description format 📝",
                        "enum": [
                            "all",
                            "text",
                            "html",
                            "markdown"
                        ],
                        "type": "string",
                        "description": "Which description representations to include (only with 'Include job details'): all, plain text, HTML, or Markdown.",
                        "default": "all"
                    },
                    "compact": {
                        "title": "Compact output 📦",
                        "type": "boolean",
                        "description": "Return only core fields (title, company, location, salary, dates, URLs) — handy for AI/agent workflows.",
                        "default": false
                    },
                    "excludeEmptyFields": {
                        "title": "Exclude empty fields 🧹",
                        "type": "boolean",
                        "description": "Remove fields that are null or empty from each output record.",
                        "default": false
                    },
                    "incrementalMode": {
                        "title": "Incremental mode 🔁",
                        "type": "boolean",
                        "description": "Classify each job as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED against the previous run and, by default, emit only NEW/UPDATED/REAPPEARED.",
                        "default": false
                    },
                    "stateKey": {
                        "title": "State key 🔑",
                        "type": "string",
                        "description": "Optional stable name for the tracking state so separate schedules don't clash. Leave blank to derive it automatically from the search parameters."
                    },
                    "emitUnchanged": {
                        "title": "Emit unchanged 🔂",
                        "type": "boolean",
                        "description": "Also output jobs that haven't changed since the last run.",
                        "default": false
                    },
                    "emitExpired": {
                        "title": "Emit expired 🗑️",
                        "type": "boolean",
                        "description": "Also output jobs that were tracked before but have now disappeared from the search (changeType = EXPIRED).",
                        "default": false
                    },
                    "skipReposts": {
                        "title": "Skip reposts ♻️",
                        "type": "boolean",
                        "description": "Detect and drop reposts — the same job (same company, title and location) re-listed under a new ID. Cross-run detection uses incremental state; kept jobs are tagged with isRepost / repostOfId.",
                        "default": false
                    },
                    "telegramToken": {
                        "title": "Telegram bot token ✈️",
                        "type": "string",
                        "description": "Bot token from @BotFather. Leave blank to skip Telegram."
                    },
                    "telegramChatId": {
                        "title": "Telegram chat ID ✈️",
                        "type": "string",
                        "description": "Chat or channel ID to send to (e.g. from @userinfobot). Required with the bot token."
                    },
                    "slackWebhookUrl": {
                        "title": "Slack webhook URL 💬",
                        "type": "string",
                        "description": "Slack Incoming Webhook URL (https://hooks.slack.com/services/...). Leave blank to skip Slack."
                    },
                    "discordWebhookUrl": {
                        "title": "Discord webhook URL 🎮",
                        "type": "string",
                        "description": "Discord channel webhook URL. Leave blank to skip Discord."
                    },
                    "webhookUrl": {
                        "title": "Generic webhook URL 🪝",
                        "type": "string",
                        "description": "POST a structured JSON payload (run metadata + job records) here — handy for n8n, Make or Zapier. Leave blank to skip."
                    },
                    "webhookHeaders": {
                        "title": "Generic webhook headers",
                        "type": "object",
                        "description": "Optional custom HTTP headers for the generic webhook, e.g. {\"Authorization\": \"Bearer ...\"}."
                    },
                    "notificationLimit": {
                        "title": "Max jobs per notification",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many jobs to list in the message (the message also reports the total matched).",
                        "default": 5
                    },
                    "notifyOnlyChanges": {
                        "title": "Notify only on changes",
                        "type": "boolean",
                        "description": "Only notify about NEW/UPDATED/REAPPEARED jobs. Requires Incremental mode; ignored otherwise.",
                        "default": false
                    },
                    "includeRunSummary": {
                        "title": "Include run summary",
                        "type": "boolean",
                        "description": "Prepend a one-line summary (country, match count, query) to each notification.",
                        "default": true
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency ⚡",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many requests to run in parallel. The actor uses geo-targeted residential proxies automatically, so raising this mainly trades speed for cost.",
                        "default": 5
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
