# Seek Jobs Scraper - Australia & New Zealand (`s-r/seek-jobs-scraper`) Actor

Search Seek and get every listing as structured data: title, company, location, category, work type and arrangement, posting date, and the pay text with real numbers parsed out of it only when the advertiser actually stated one. Australia and New Zealand.

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

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Seek Jobs Scraper - Australia & New Zealand

Search Seek and get every listing back as a structured row: title, company,
location, category, work type, work arrangement, posting date, and the pay.

Type a keyword, a location, or both. No API key, no login.

### What you get per listing

**The job** — `title`, `url`, `teaser` (the summary line on the card) and
`bullet_points` (the selling points the advertiser chose).

**Who is hiring** — `company`, `company_url` where Seek has a profile, and
`advertiser_id`. Recruiters and direct employers both appear, and the advertiser
id is what tells you the same agency is behind fifteen of your rows.

**Where** — `location`, `all_locations` when a listing names several, and
`region` for the state or territory it sits in.

**What kind of job** — `classification` and `sub_classification` from Seek's own
taxonomy, `work_types` (full time, contract, casual) and `work_arrangements`
(on-site, hybrid, remote) where the advertiser stated one.

**When** — `listing_date` as a UTC timestamp and `listing_age` as Seek phrases
it ("1d ago").

**Placement** — `is_sponsored` and `is_featured`.

**Pay** — see below. This is the part worth reading.

### About the salary, which is the field everyone gets wrong

Seek does not publish a salary number. It publishes **a line of text the
advertiser typed**, and the advertiser can type anything. From a single page of
results:

```
$150,000 – $160,000 per year                        a real range
$90,000 – $95,000 + Super + Bonus                   a range plus extras
Up to $95,170 depending on qualifications            a ceiling, not a range
$120 - $140 - inc Super - Weekly Pay Options         an hourly rate, paid weekly
Suited to detail-oriented engineers with strong QA   not a salary at all
Attractive salary + bonus + benefits                 not a salary at all
                                                     most of them, blank
```

Treating that field as a number is how a "roles over $100k" filter quietly ends
up including jobs whose pay is unknown and excluding jobs that pay well. So this
Actor returns both:

- `salary_label` — the text exactly as written, always, whatever it says
- `salary_min`, `salary_max`, `salary_period` — filled **only** when the text
  genuinely reads as money
- `salary_is_stated` — the flag that lets you tell "no pay stated" apart from
  "the label was marketing copy"

`salary_max` stays empty when the advertiser gave a single figure, because
repeating it as a maximum invents a range nobody offered. `Up to $95,170`
becomes a maximum with **no minimum**, because it promises no floor.

#### Pay periods, and one specific trap

A results page mixes annual salaries and hourly contractor rates freely, and
`45` sitting next to `150000` in one column is worse than an empty column. Every
parsed amount carries `salary_period`, so you can compare like with like.

The trap is that a period word in the text often describes **how often you are
paid**, not what the rate is in. `$120 - $140 - inc Super - Weekly Pay Options`
is an hourly rate offering weekly payment; read literally it says someone earns
$140 a week. When the wording and the amount disagree, the amount decides, so
that listing comes back as hourly.

Roughly **a third** of listings state a real amount. The run summary reports
`withStatedSalary` and `withSalaryLabelButNoAmount` so you always know how much
of a run carried one rather than assuming.

### Sponsored placement is marked, so position is not a ranking

Employers pay for placement on Seek, and a sponsored ad sits above organic
results. A row's `position` therefore reflects what Seek chose to show, not
relevance or recency. `is_sponsored` lets you drop the paid slots, or study them
on purpose: which agencies are paying to be seen is a useful signal in itself.

### Australia and New Zealand are separate boards

`seek.com.au` and `seek.co.nz` carry different listings, and the **Country**
input picks between them. A search of one never returns the other's jobs, so a
national picture means two runs.

### Filters and scale

Seek returns 32 listings per page. **Maximum jobs** rounds up to whole pages and
is the ceiling on both time and cost: 96 jobs is three pages. Forty jobs across
two pages took **under nine seconds** in testing.

The summary also reports `totalMatchingOnSeek`, the count Seek itself claims for
your search. When that reads 22,482 and you asked for 96, you know exactly how
much of the board you are looking at. That number is Seek's, reported as given.

### What people use this for

**Salary benchmarking.** The subset of listings that state a real amount is a
genuine sample of advertised pay by role, location and seniority. `salary_period`
keeps hourly contract work from contaminating an annual average, and
`salary_is_stated` keeps blank labels from being counted as zero.

**Recruitment intelligence.** `advertiser_id` and `company` across repeated runs
show who is hiring, how fast, and which agencies dominate a category. New
listings appearing under a competitor's name is a hiring-velocity series.

**Market monitoring.** Run a search on a schedule and keep the rows.
`listing_date` and the disappearance of an id tell you how long a role stayed
open, which is a fair proxy for how hard it was to fill.

**Job aggregation.** One search, one table, one shape, with the pay already
separated into text and numbers so you do not have to write that parser.

### Notes

Only currently open listings appear. A filled or withdrawn role stops being
published, which is what makes the run-on-a-schedule pattern above work.

A search that matches nothing is reported as exactly that, with the search
spelled out, rather than as an empty result you would have to interpret.
Occasionally a page needs a second attempt before it comes through; that is
handled inside the run, and only a page that never arrives is reported.

# Actor input Schema

## `keywords` (type: `string`):

What to search for, exactly as you would type it into Seek's search box, for example "data scientist" or "registered nurse". Leave empty to list everything in a location.

## `where` (type: `string`):

Where to search, in Seek's own format, for example "Sydney NSW", "Melbourne VIC" or "Auckland". Leave empty to search the whole country.

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

Which Seek site to search. Australia and New Zealand are separate job boards with separate listings.

## `max_jobs` (type: `integer`):

Stop after this many jobs. Seek returns 32 per page, so this rounds up to whole pages and is also the cost ceiling for the run.

## Actor input object example

```json
{
  "keywords": "software engineer",
  "where": "Melbourne VIC",
  "country": "au",
  "max_jobs": 96
}
```

# Actor output Schema

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

One row per listing.

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

Jobs returned, pages read, how many stated a salary, and the total Seek reports for the search.

## `errors` (type: `string`):

Pages that could not be read, with a code and a redacted message.

# 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 = {
    "keywords": "data scientist",
    "where": "Sydney NSW"
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = {
    "keywords": "data scientist",
    "where": "Sydney NSW",
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/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 '{
  "keywords": "data scientist",
  "where": "Sydney NSW"
}' |
apify call s-r/seek-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/k3m9rPJ0krjnvVSa6/builds/FtFXi2yJC3FdKeW5Q/openapi.json
