# SEEK Jobs Scraper - Australia & New Zealand Job Ads API (`rel8ble/seek-jobs-scraper`) Actor

Use this to get job ads from SEEK (seek.com.au, seek.co.nz). Input: keywords, locations, filters or SEEK URLs. One result = one job: title, company, location, salary, work type, category, date, URL; optional full description and company profile. Not capped at 550 jobs. $0.80 per 1,000.

- **URL**: https://apify.com/rel8ble/seek-jobs-scraper.md
- **Developed by:** [Giovanni Rich](https://apify.com/rel8ble) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.80 / 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/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

## SEEK Jobs Scraper & API - Australia and New Zealand job ads (seek.com.au, seek.co.nz)

**SEEK Jobs Scraper** is a SEEK scraper and unofficial SEEK jobs API for **seek.com.au** and **seek.co.nz**. Give it keywords, locations and filters (or paste SEEK search URLs) and get every matching job ad as clean JSON, CSV or Excel: title, company, location, salary (as written and as numbers), work type, on-site / hybrid / remote, classification, listing date, the job URL and, if you want it, the full description and the company profile (website, industry, size, rating).

It reads the same JSON the SEEK website loads, over plain HTTP: no browser and no login, so 100 jobs arrive per request and a run of 8,500 jobs takes about 80 seconds. SEEK shows at most 550 jobs for any one search; this scraper **splits big searches automatically** by category, sub-category, work type and work arrangement and merges the results without duplicates, so a search with 8,877 jobs returned 8,539 of them in testing instead of 550.

Use it for **hiring-signal lead generation** (which Australian and New Zealand companies are hiring for what, right now), job boards and aggregators, recruitment market mapping, salary benchmarking and labour-market research.

### How to use

1. Type one or more **Search keywords** (`data analyst`, `registered nurse`, `forklift`) and, optionally, **Locations** (`Sydney NSW`, `All Melbourne VIC`, `Auckland`). Every keyword is searched in every location. No keyword = all jobs matching your location and filters.
2. Pick the **Country / site**: Australia or New Zealand.
3. Optionally filter: **Classification** (30 job categories), **Work types**, **Work arrangements** (on-site, hybrid, remote), **Posted within (days)**, **Minimum / Maximum salary** and **Sort order**.
4. Set **Max jobs per search** (0 = everything). Tick **Include full description & company profile** if you need the ad text.
5. Click **Start**. Download the results as JSON, CSV, Excel or HTML from the **Output** tab, or pull them through the Apify API, Make, Zapier, n8n or an MCP client.

Already have links? Paste SEEK **search URLs** or **job URLs** into *Search or job URLs* instead; the filters in a search URL are read from the URL.

### What you get

One dataset item per job ad:

- **Identity**: `id` (SEEK job id, stable across runs), `title`, `url`, `site`, `country`.
- **Company**: `company`, `advertiserName` and `advertiserId` (the account that posted the ad, which can be a recruiter), `companyId`, `companyProfileUrl`, `companyLogoUrl`.
- **Where**: `location`, `locations`, `area` (the wider region), `countryCode`.
- **Work**: `workType` (Full time, Part time, Contract/Temp, Casual/Vacation), `workArrangement` (On-site, Hybrid, Remote), `isRemote`.
- **Pay**: `salaryText` exactly as the advertiser wrote it, plus `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod` (hour, day, month, year) parsed from it when the text has clear numbers.
- **Category**: `classification`, `subclassification` and `classifications` (an ad can sit in two).
- **Ad text**: `teaser`, `bulletPoints`.
- **Dates and flags**: `listedAt`, `isFeatured`, `isSponsored`, `isExpiringSoon`.
- **Where it came from**: `sourceQuery`, `sourceLocation`, `position`, `scrapedAt`.

With **Include full description & company profile** on, each job also gets `description` (plain text), optional `descriptionHtml`, `expiresAt`, `status`, `appliesOnCompanySite`, `isVerifiedAdvertiser`, `advertiserSince`, `screeningQuestions`, and from the company's SEEK profile where one exists: `companyWebsite`, `companyIndustry`, `companySize`, `companyRating`, `companyReviewCount`, `companyDescription`, `companyPerks`, `companyJobsUrl`.

### Use cases

- **Lead generation from hiring signals**: a company advertising for three payroll officers is a prospect for payroll software; one hiring site managers in Perth needs equipment and labour hire. Run your keywords daily with *Posted within 1 day* and send new ads to your CRM with the company website attached.
- **Recruitment agencies**: see who is hiring in your niche, which ads are direct employers and which are other agencies (`advertiserName` vs `company`), and how long ads stay up.
- **Job boards and aggregators**: pull a category or a whole region into your own feed, deduplicated by `id`.
- **Salary benchmarking**: `salaryMin` / `salaryMax` by role, city and work type, from ads that publish pay.
- **Labour-market research**: job counts by classification, location and remote share over time.
- **AI agents**: "find remote data engineer jobs in Australia paying over $150k posted this week" maps straight onto the input fields.

### Input example

| Field | Default | Description |
|---|---|---|
| `searchQueries` | - | Keywords, one search each. Empty = all jobs matching the filters |
| `locations` | whole country | Locations as SEEK writes them: `Sydney NSW`, `All Melbourne VIC`, `Auckland`, a suburb or a postcode |
| `country` | `AU` | `AU` (seek.com.au) or `NZ` (seek.co.nz) |
| `classification` | `any` | One of SEEK's 30 categories; via API also `"Accounting > Payroll"` or an id |
| `workTypes` | all | Any of `fulltime`, `parttime`, `contract`, `casual` |
| `workArrangements` | all | Any of `onsite`, `hybrid`, `remote` |
| `postedWithinDays` | 0 (any) | 1 = listed today, 3, 7, 14, 31 |
| `salaryMin` / `salaryMax` | 0 | In the unit set by `salaryType` |
| `salaryType` | `annual` | `annual`, `monthly` or `hourly` |
| `sort` | `relevance` | `relevance` or `date` |
| `maxItems` | 100 | Max jobs per search; 0 = all |
| `deepSearch` | true | Split searches above 550 jobs so nothing is cut off |
| `includeDetails` | false | Full description, expiry, screening questions, company profile (one extra request per job) |
| `includeDescriptionHtml` | false | Also keep the description HTML |
| `startUrls` | - | SEEK search URLs, job URLs or bare job ids |
| `proxyConfiguration` | Apify datacenter | No residential proxies needed |

Remote or hybrid data jobs across Australia paying $120k or more, listed this week, with descriptions:

```json
{
    "searchQueries": ["data engineer", "data analyst"],
    "country": "AU",
    "workArrangements": ["hybrid", "remote"],
    "salaryMin": 120000,
    "salaryType": "annual",
    "postedWithinDays": 7,
    "maxItems": 200,
    "includeDetails": true
}
```

Every nurse job in the Healthcare & Medical category in New Zealand, no cap:

```json
{
    "country": "NZ",
    "classification": "Healthcare & Medical",
    "searchQueries": ["nurse"],
    "maxItems": 0
}
```

From links you copied off the site:

```json
{
    "startUrls": [
        "https://www.seek.com.au/data-analyst-jobs/in-All-Melbourne-VIC/full-time?daterange=7",
        "https://www.seek.com.au/job/95126283"
    ]
}
```

### Output example

From a real run (search for `data engineer` in Sydney NSW, details on; long texts shortened):

```json
{
    "id": "95195166",
    "title": "Research Data Storage Specialist",
    "company": "The University of Sydney",
    "location": "Sydney NSW",
    "locations": [
        "Sydney NSW"
    ],
    "area": "New South Wales NSW",
    "countryCode": "AU",
    "workType": "Full time",
    "workTypes": [
        "Full time"
    ],
    "workArrangement": "Hybrid",
    "workArrangements": [
        "Hybrid"
    ],
    "isRemote": false,
    "salaryText": "$152,045 to $160,430 + 17% Superannuation",
    "salaryMin": 152045,
    "salaryMax": 160430,
    "salaryCurrency": "AUD",
    "salaryPeriod": "year",
    "classification": "Information & Communication Technology",
    "subclassification": "Database Development & Administration",
    "classifications": [
        "Information & Communication Technology > Database Development & Administration"
    ],
    "teaser": "Support pivotal research infrastructure systems that enable world-class research at the University of Sydney.",
    "bulletPoints": [
        "Support world-class research through enterprise-scale data storage and managemen",
        "Enable researchers to tackle complex data-intensive workloads and scientific cha",
        "Salary range between $152,045 to $160,430 + 17% Superannuation"
    ],
    "listedAt": "2026-10-12T01:01:13.000Z",
    "isFeatured": false,
    "isSponsored": false,
    "isExpiringSoon": false,
    "advertiserId": "63582582",
    "advertiserName": "The University of Sydney",
    "companyId": "432709",
    "companyProfileUrl": "https://au.seek.com/companies/the-university-of-sydney-432709",
    "companyLogoUrl": "https://bx-branding-gateway.cloud.seek.com.au/9c3b52ee-817b-4f0c-8130-ed06d4c42912.1/jdpLogo",
    "roleId": "storage-specialist",
    "url": "https://www.seek.com.au/job/95195166",
    "site": "seek.com.au",
    "country": "Australia",
    "sourceQuery": "data engineer",
    "sourceLocation": "Sydney NSW",
    "position": 32,
    "scrapedAt": "2026-10-13T17:42:53.962Z",
    "description": "Solve by Talent is partnering with the University of Sydney to recruit a Research Data Storage Specialist within Information and Communications Technology (ICT). This rol ...",
    "expiresAt": "2026-10-26T01:15:00.000Z",
    "isExpired": false,
    "status": "Active",
    "appliesOnCompanySite": false,
    "isVerifiedAdvertiser": true,
    "advertiserSince": "2026-03-19T03:27:45.271Z",
    "screeningQuestions": [
        "Which of the following statements best describes your right to work in Australia?",
        "What's your expected annual base salary?",
        "How much notice are you required to give your current employer?"
    ],
    "companyWebsite": "http://sydney.edu.au/",
    "companyIndustry": "Education, Training & Professional Development",
    "companySize": null,
    "companyRating": 3.2,
    "companyReviewCount": 147,
    "companyDescription": "The University of Sydney has believed in education for all and leadership that make lives better. The same values continue to inform the org ...",
    "companyPerks": [],
    "companyJobsUrl": "https://au.seek.com/The-University-of-Sydney-jobs/at-this-company"
}
```

Fill rates on an 8,539-job test run (`nurse`, all of Australia): id, title, company, location, area, work type, work arrangement, classification, sub-classification, teaser, listing date and URL 100%; advertiser id 99%; company logo 75%; bullet points 70%; company profile link 62%; salary text 53%; parsed salary numbers 43%. On a 301-job run with details: description, expiry date and status 100%; screening questions 39%; company industry 34%; company size 28%; company website 27%; company rating 26% (company fields exist only for employers with a SEEK company profile). A field SEEK does not publish for a job is `null`, never guessed.

### Pricing

Pay per result: **$0.80 per 1,000 jobs** (one result = one job ad saved to the dataset). The full description and company profile are included in that price.

- 100 jobs for a quick search = $0.08
- Every `nurse` job in Australia, about 8,500 jobs = $6.80
- A daily run of 20 keywords, new ads only (about 300 jobs) = $0.24 a day

No start fee and no charge per search. Failed requests, duplicate ads, expired job URLs and empty searches are never charged. If you set a maximum cost per run, the scraper stops cleanly when it reaches it. Apify's free plan includes $5 of monthly platform credit, enough for about 6,000 jobs.

### Integrations

- **Make, Zapier and n8n**: start runs and push new jobs to your CRM, Slack, Google Sheets or Airtable.
- **Google Sheets**: export the dataset straight into a spreadsheet, or refresh it on a schedule.
- **Apify API**: run the actor and fetch results over REST, or with the official JavaScript and Python clients.
- **Webhooks**: get notified when a run finishes and process the data right away.
- **Schedules**: run daily with `postedWithinDays: 1` and deduplicate by `id` to collect only new ads.
- **MCP for AI agents**: through the Apify MCP server (https://mcp.apify.com), Claude, ChatGPT, Cursor and other agents can call this SEEK jobs API directly and read the results.

### Limits (read before large runs)

- **550 jobs per single search** is SEEK's own limit. Deep search gets around it by splitting; on the largest test (8,877 listed) it returned 96%. A slice that is still above 550 after every split is fetched in both sort orders, and the run summary counts those slices (`searchesCappedAt550`).
- **SEEK's totals are estimates.** The `siteTotal` in the run summary can differ from the number of unique jobs by a few percent, and the same ad can be listed twice (sponsored and organic); duplicates are dropped and not charged.
- **Locations must be ones SEEK recognises.** An unknown location returns 0 jobs and the summary says so.
- **Salary numbers are parsed from free text.** About half of all ads show a salary line and some of those are slogans ("Competitive salary"); those keep `salaryText` and leave the numbers `null`.
- **Ads live about 30 days**, so `postedWithinDays` above 31 has no effect.
- **No applicant or personal data.** The scraper returns the public job ad and company profile only; recruiter phone numbers and emails are not collected.
- **Details cost one request per job**: about 160 jobs a minute instead of several thousand.

### FAQ

**Is there an official SEEK API for job search?**
SEEK's official API is for hirers and recruitment software posting ads, not for reading the job market. This actor is an unofficial alternative that reads the public search results.

**Can I scrape Jobstreet or JobsDB as well?**
Yes, with the sister actor [Jobstreet & JobsDB Jobs Scraper](https://apify.com/rel8ble/jobstreet-jobsdb-scraper) (Malaysia, Singapore, Philippines, Indonesia, Hong Kong, Thailand). Same input and output fields.

**How do I get only new jobs every day?**
Schedule the actor daily with `postedWithinDays: 1` and `sort: "date"`, and deduplicate on `id` in your own system.

**How do I find companies, not recruiters?**
Compare `company` with `advertiserName`; when they differ the ad was placed by an agency. With details on, `companyWebsite` is filled for companies that have a SEEK profile.

**Why did I get fewer jobs than SEEK's count?**
SEEK's count includes duplicates and is rounded. Check `RUN_SUMMARY` in the key-value store: it lists each search with the site total, pages fetched and why it stopped.

**Is scraping SEEK legal?**
The actor collects publicly visible job ads, not personal data. You are responsible for how you use the data and for following SEEK's terms and the laws that apply to you.

**Something is wrong or a field is missing.**
Open an issue on the Issues tab of the actor page with the run ID. It reaches the developer directly.

# Actor input Schema

## `searchQueries` (type: `array`):

Optional. Job keywords as typed into the SEEK search box, one per line: "data analyst", "registered nurse", "forklift". A company name also works. Each keyword is one search and returns up to maxItems jobs. Leave empty to list all jobs matching the location and filters below. Give at least one of searchQueries, locations, a filter or startUrls.

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

Optional. Where to search, one per line, written the way the site shows it: "Sydney NSW", "All Melbourne VIC", "Brisbane QLD", "Perth WA", "Auckland", a suburb ("Parramatta NSW") or a postcode ("3000"). Every keyword is searched in every location (2 keywords x 3 locations = 6 searches). Empty = the whole country. A location the site does not recognise returns 0 jobs and is named in the run summary.

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

Which site to search: "AU" = Australia (seek.com.au), "NZ" = New Zealand (seek.co.nz). One country per run; start another run for another country. Default "AU".

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

Optional. Limit every search to one of the 30 job categories, e.g. "Information & Communication Technology", "Healthcare & Medical", "Accounting". "any" (default) = no limit. Through the API you can also pass a sub-category as "Accounting > Payroll" or a numeric id such as "6281".

## `workTypes` (type: `array`):

Optional. Keep only these work types: any of "fulltime", "parttime", "contract", "casual". Empty = all work types.

## `workArrangements` (type: `array`):

Optional. Keep only these arrangements: any of "onsite", "hybrid", "remote". Use \["remote"] for remote jobs only. Empty = all.

## `postedWithinDays` (type: `integer`):

Optional. Only jobs listed in the last N days, integer 0-31: 1 = listed today, 3, 7, 14 or 31 are the usual choices. 0 (default) = any date (ads stay up about 30 days). Use 1 on a daily schedule to collect only new jobs.

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

Optional. Lowest pay to include, in the site currency and the unit chosen in salaryType: 100000 with "annual" = jobs paying at least $100,000 a year. 0 (default) = no minimum. The site matches on the pay range the advertiser entered, including ads that hide the figure.

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

Optional. Highest pay to include, same unit as salaryMin. 0 (default) = no maximum.

## `salaryType` (type: `string`):

Optional. Unit of salaryMin / salaryMax: "annual", "monthly" or "hourly". Default "annual". Ignored when both salary fields are 0.

## `sort` (type: `string`):

Optional. "relevance" (default) or "date" (newest first; sponsored ads still appear near the top, flagged isSponsored).

## `maxItems` (type: `integer`):

Optional. Maximum jobs saved per search (one keyword in one location), integer >= 0. Default 100; 0 = every job the search has. You pay per job saved ($0.0008 each), so 100 jobs = $0.08. Use 10-20 for a quick answer.

## `deepSearch` (type: `boolean`):

Optional boolean, default true. The site returns at most 550 jobs for any one search. With deep search on, a bigger search is split automatically by category, sub-category and work type and the results are merged without duplicates, so "nurse" in all of Australia returns thousands of jobs instead of 550. Only kicks in when maxItems is above 550 (or 0). It costs extra requests, not extra money per job.

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

Optional boolean. false (default) = listing data only: title, company, location, salary, work type, category, teaser, bullet points, dates, links; 100 jobs per request. true = also open each job to add the full description (plain text), expiry date, screening questions, whether you apply on the company site, and the company profile where one exists (website, industry, size, rating, review count). One extra request per job, same price per result.

## `includeDescriptionHtml` (type: `boolean`):

Optional boolean. Only used with includeDetails. true = add descriptionHtml (the original formatting) next to the plain-text description. Default false.

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

Optional. URLs copied from the site, one per line. A search results URL ("https://www.seek.com.au/data-analyst-jobs/in-All-Melbourne-VIC?daterange=7") is scraped with the filters in the URL (the filter fields above are not applied to it). A job URL ("https://www.seek.com.au/job/95126283") or a bare job id ("95126283") is looked up directly and always includes the full details. A job that has expired is listed in the run summary and is not charged.

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

Optional, advanced. Number of parallel requests, integer 1-20. Default 8. Leave unset.

## `maxRequestRetries` (type: `integer`):

Optional, advanced. Retries per failed or blocked request, integer 0-20; each retry uses a new session and IP. Default 8. Leave unset.

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

Optional, advanced. Apify Proxy settings object. Default {"useApifyProxy": true} (datacenter proxies are enough). Leave unset.

## Actor input object example

```json
{
  "searchQueries": [
    "data analyst"
  ],
  "country": "AU",
  "classification": "any",
  "postedWithinDays": 0,
  "salaryMin": 0,
  "salaryMax": 0,
  "salaryType": "annual",
  "sort": "relevance",
  "maxItems": 20,
  "deepSearch": true,
  "includeDetails": false,
  "includeDescriptionHtml": false,
  "maxConcurrency": 8,
  "maxRequestRetries": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All jobs found: title, company, location, salary (text and parsed numbers), work type, work arrangement, classification, teaser, bullet points, listing date, job URL and company links (plus full description, expiry date and company profile when details are on).

## `summary` (type: `string`):

Per-search counts, the totals the site reported, how many narrower searches deep search ran, stop reasons and the list of anything that failed.

# 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 = {
    "searchQueries": [
        "data analyst"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/seek-jobs-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 = {
    "searchQueries": ["data analyst"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rel8ble/seek-jobs-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 '{
  "searchQueries": [
    "data analyst"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rel8ble/seek-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rel8ble/seek-jobs-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/GeaKYlgseGOIcRBuk/builds/qQVzIU3Rz9NIJPc62/openapi.json
