SEEK Jobs Scraper icon

SEEK Jobs Scraper

From $0.7/1K. Scrape SEEK.com.au and SEEK.co.nz jobs by keyword, location, or filters. Extract full descriptions, companies, salaries, locations,…

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

SEEK Jobs Scraper at a glance

SEEK Jobs Scraper is a ready-to-run Apify actor from abotapi for collecting jobs data. Its documented output includes title, company, location, salary and listed, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.40 per 1,000 results on the Apify Free plan and from $0.70 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Jobs, Developer Tools, Automation
Pricing
$1.40 per 1,000 results (Free plan), from $0.70 on paid plans
Output
Documented below · JSON, CSV, Excel
Inputs
45 options
Run success
99.5% of completed public runs in the last 30 days

From $0.7/1K. Scrape SEEK.com.au and SEEK.co.nz jobs by keyword, location, or filters. Extract full descriptions, companies, salaries, locations, classifications, listing dates, and more across Australia and New Zealand.

What SEEK Jobs Scraper can do

  • Two ways to search. Build a query from keywords, location and filters, or paste one or more SEEK search URLs and skip the filter fields entirely.
  • AU and NZ in one run. URL mode auto-detects the market per link, so seek.com.au and seek.co.nz URLs can be mixed in the same input.
  • Full detail on demand. Turn on Fetch full job description for the HTML and plain text body, ad bullet points, published contacts and the employer's company profile.
  • Parsed, not just displayed, salary. A minimum, maximum, period and currency are parsed out of SEEK's free text salary label.
  • Employer profiles included. Industry, size, website, specialities, star rating, review count, perks and awards for the hiring company.
  • Wide filter set. Classification, work type, work arrangement, salary range and listing date, or the full SEEK URL grammar in URL mode.

Choose what to collect

These inputs let you configure SEEK Jobs Scraper - Australia & New Zealand Job Listings. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestringAuto (default): if you edit the 'SEEK search URLs' list the actor scrapes those links, otherwise it runs the search fields. Search: always use the keyword, location and filter fields; pasted links are ignored. URL: always scrape the links in the list. Left unedited, that list holds one example of each supported link shape.

Choices: auto, search, url

regionstringCountry market to search. AU = seek.com.au, NZ = seek.co.nz.

Choices: AU, NZ

keywordsstringJob title or keywords (e.g. 'software engineer'). Leave empty to match all jobs in the location.
keywordsListarrayRun one extra search per entry (e.g. 'registered nurse', 'midwife') on top of Keywords above, with the same filters. Results from every search are merged and de-duplicated by job, and all searches share the one 'Max items to return' cap, filled in order. Leave empty for a single search.
companyNamestringOptional. Only jobs advertised by this employer, matched on SEEK's own company filter (exact name, any case), e.g. 'Turner & Townsend' or 'Amplar Health'. Works with Keywords and Location. A name SEEK has no jobs for returns no results. The same filter a SEEK 'jobs at this company' link applies, and the value of the companyOpenJobs output field.
locationstringWhere to search, as a plain place name: a suburb, city, area, state or postcode. AU examples: 'Sydney', 'All Melbourne VIC', 'Parramatta NSW 2150', 'All-Australia', 'Brisbane CBD & Inner Suburbs'. NZ examples: 'Auckland', 'Wellington', 'All-New-Zealand'. The log shows which SEEK location your text matched, and a name SEEK does not recognise is reported by name instead of returning a silent empty run.
locationsListarrayRun the search in each of these locations too (e.g. 'Sydney', 'Melbourne VIC'). Combined with More keyword searches, every keyword is searched in every location. If Location above is still on its default 'All-Australia', it is replaced by this list rather than run as an extra country-wide search.
Show 38 more inputs
More input fields
InputWhat it controls
radiusintegerOnly include jobs within this many kilometres of a suburb or city Location (SEEK's own distance filter). SEEK accepts 1-100 km and uses 50 km when this is empty; it has no effect on state- or country-wide locations.
classificationarrayFilter by one or more top-level classifications. Leave empty for all. To narrow further, pick a Subclassification below.
subclassificationarrayFilter by one or more specific roles inside a classification (e.g. 'Information & Communication Technology › Developers/Programmers'). Works on its own or together with Classification. Leave empty for all. A few government options exist only on SEEK Australia or only on SEEK New Zealand, as marked.
workTypearrayFilter by one or more work types. Leave empty for all.
workArrangementarrayFilter by where the job is done. Leave empty for all arrangements.
salaryTypestringThe unit the salary range below is measured in. Choose 'Hourly rate' for hourly-paid roles, then enter the range in dollars per hour (e.g. 30 to 60), not per year, or 'Monthly salary' to enter it per month (e.g. 8000 to 12000).

Choices: annual, monthly, hourly

salaryMinintegerOptional minimum salary, in the unit chosen above. Rounded down by SEEK.
salaryMaxintegerOptional maximum salary, in the unit chosen above.
daterangeintegerOnly return jobs listed in the last N days. SEEK only accepts one of: 1, 3, 7, 14, 31. Other values are dropped with a warning.
sortmodestringNewest first (SEEK's listed date) or most relevant (SEEK's keyword relevance).

Choices: ListedDate, KeywordRelevance

urlsarraySEEK links to scrape. Supported: search pages (any depth: classification, subclassification, keyword, location, work type, work arrangement, up to four path segments?advertiserid=?where=?page=N to start at that page), employer links like /National-Civil-&-Foundations-Pty-Ltd-jobs and /Turner-&-Townsend-jobs/at-this-company (that employer's jobs only), a bare place name like /jobs/in-Wellington (searched as SEEK's whole-area page, All Wellington), locations with a comma, au.seek.com / nz.seek.com and the older www and m. hosts, a single job's /job/ or ?jobId= share link (fetched directly, never re-searched), and a company profile /companies/ (resolved to that employer's job search by reading its advertiser id off one of its own current job ads, with a per-link warning if it has none). A job link whose ad has since closed gives a warning for that link and the rest still run. Pages that are not searches (the home page, directories, career advice) are skipped with a warning. See the README's URL-mode table.
includeKeywordsarrayKeep only jobs that mention at least one of these words in the title, company or advertiser name, teaser, summary, ad bullet points or, when 'Fetch full job description' is on, the full description. Not case-sensitive. Matches whole words, so 'java' does not match 'javascript'.
excludeKeywordsarrayDrop jobs that mention any of these words, checked against the same text as Include keywords. Not case-sensitive and matches whole words.
keywordMatchFieldsarrayWhich parts of each job Include keywords and Exclude keywords are checked against. Leave empty to check the title, company, description (teaser, summary and, when 'Fetch full job description' is on, the full text) and bullet points, the same as before this option existed. Pick 'Title' alone to match job titles only. 'Category' (SEEK classification and sub-classification) is only checked when you pick it. Has no effect unless Include or Exclude keywords is set.
fromDatestringKeep only jobs listed at or after this date or time (UTC unless the value includes an offset). Format: 2026-10-01 or 2026-10-01T09:00:00+10:00.
toDatestringKeep only jobs listed at or before this date or time. A date on its own includes that whole day (UTC). Same format as above.
maxAgeMinutesintegerKeep only jobs listed in the last N minutes before the run started (e.g. 60 for the past hour). Finer than 'Listed within N days'. Combined with 'Listed on or after', the later of the two cut-offs applies.
minApplicantsintegerKeep only jobs with at least this many applicants. Applicant numbers come from each job's full details, so this turns on 'Fetch full job description' for the run (billed per pushed job as detail enrichment). Jobs where SEEK shows no applicant count yet, often ones listed in the last few hours, are removed.
maxApplicantsintegerKeep only jobs with at most this many applicants, to find roles with less competition. Like Minimum applicants, this turns on full job details, and jobs with no applicant count are removed.
requireContactstringKeep only jobs that publish contact details (phone or email found in the ad's contact block or description). Turns on full job details for the run (billed per pushed job as detail enrichment).

Choices: off, email, phone, either, both

skipRepostsbooleanDrop jobs flagged as reposts: the same advertiser re-listing the same title in the same location under a new job ID. With Incremental mode on, jobs are checked against every job the saved search has ever tracked, including expired ones. Without it, only jobs seen in the same run are checked. Every job carries isRepost and repostOfId either way.
customFiltersarrayAdvanced: keep only jobs whose OUTPUT fields pass every rule. Each rule is {"field": "salaryMin", "op": "gte", "value": 120000}. Ops: includes, notIncludes (text contains, any case; for lists, any element), equals, notEquals, gt, gte, lt, lte (numbers). A field may be a dotted path such as recruiterProfile.rating. An unknown field or op fails the run up front instead of silently removing every job. Rules on fields that only come with the full description (e.g. companyRating, numApplicants, emails) switch 'Fetch full job description' on. Like the other post-filters, a removed job is never pushed or charged.
includeFullDescriptionbooleanIf true, each job also gets: the full description (HTML + plain text + sections), the ad's bullet points, expiry date, application-type flag, contact details when published, and the employer's company block, industry, company size, website, specialities, star rating, review count, and perks. Leave off for a faster, lighter run that returns search-card fields only.
descriptionFormatstringWhich copies of the job description each row carries. The default keeps the HTML (content) and plain text (contentText), as before. 'Markdown' returns contentMarkdown only (headings, bold and bullet lists kept), which is the smallest readable form for AI agents and LLM pipelines. 'All' adds contentMarkdown alongside the other two. Only applies when 'Fetch full job description' is on.

Choices: html_text, all, html, text, markdown

descriptionMaxLengthintegerCut the plain-text and Markdown description to this many characters, ending with '…'. The HTML copy is never cut (that would break its markup), so pair this with Description format 'Plain text only' or 'Markdown only' for the smallest rows. Each row then carries descriptionTruncated (true when its description was cut). 0 means no limit.
compactbooleanReturn only the core fields an AI agent or spreadsheet needs: id, links, title, company, location, classification, work type and arrangement, salary, dates, applicant count, contact details, teaser, bullet points, the description in the format chosen above, the search that found the job, and the repost and incremental-mode fields when present. Turn off to get every field.
excludeEmptyFieldsbooleanDrop fields that have no value on a row (null, empty text, empty list or empty object), including inside nested objects. false and 0 are kept. Rows get smaller, but different rows can then have different columns.
maxItemsintegerTotal cap across ALL URLs and ALL pages (not per-URL). Example: maxItems=50 with 3 URLs paginates URL 1 until the budget is filled; URLs 2 and 3 run only if budget remains. Set to 0 for unlimited.
maxTimeSecintegerWall-clock cap across ALL URLs and pages. When exceeded, the actor stops paginating, flushes whatever it already fetched to the dataset, and exits cleanly. Set to 0 for no time limit.
resumeFromRunIdstringPaste a previous run ID or dataset ID to continue an interrupted crawl: jobs already collected there are skipped so you get only what's still missing. One-off continuation of a SPECIFIC run - for ongoing scheduled monitoring of the same search, use Incremental mode below instead.
incrementalModebooleanFor a search you run on a schedule (e.g. daily/weekly): remembers what this exact search returned last time and classifies every job as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED, so you can act on only what changed. UPDATED means a real change to the job: any output field differs from the saved copy (title, description, salary, location, work type, classification, advertiser, company rating or review count, expiry or status, the listing date itself...), and changedFields names which. NOT compared, so they never cause UPDATED on their own: scrapedAt, the relative 'N ago' times (listingDateDisplay, postedTime), detailFetched, the repost flags (isRepost, repostOfId), the applicant numbers (numApplicants, applicantCountLabel, applicantVolumeLabel, resumePercentage, coverLetterPercentage), companyOpenJobs and salaryCurrency (both derived from fields that are compared); add more with Ignore fields below. If the full-description fetch fails for a job on one run, its description and company details are carried over from the saved copy instead of reading as a change. EXPIRED is only reported after a run that scanned every page of every search, so a capped, filtered or page-2-onward run never expires jobs. Off by default so existing scheduled runs are unaffected. Separate from Resume above, which continues one specific interrupted run. Uses State key below to isolate different searches; see Emit unchanged rows / Emit expired rows to control which of those get pushed (both bill extra rows when on).
stateKeystringNames the saved baseline Incremental mode compares against. Leave empty to auto-derive one from your region/keywords/location/classification/workType/workArrangement/salary/daterange/sortmode/urls/includeFullDescription (plus subclassification, the extra keyword/location lists, radius and any result filter you set) - two differently-configured searches never share a baseline even with this left empty. Set your own text only if you want to explicitly reuse or separate baselines yourself. Ignored when Incremental mode is off.
emitUnchangedbooleanWhen Incremental mode is on: also push rows classified UNCHANGED (identical to last run), not just NEW/UPDATED/REAPPEARED/EXPIRED. Off by default to save you from paying for rows that didn't change. Turning this on bills the per-result event (and the detail-enrichment surcharge, if Fetch full job description is on) for every unchanged row too.
emitExpiredbooleanWhen Incremental mode is on: push a synthetic EXPIRED row for jobs tracked in a previous run that no longer appear in this one. Only fires after a run that scanned every page of every search with no cap, time limit, or resume truncating it - a partial scan can't tell 'gone' apart from 'not reached yet', so it's skipped (with a log line) otherwise. Off by default; turning it on bills the per-result event for each EXPIRED row emitted.
ignoreFieldsForChangesarrayOptional. Field names to exclude from UPDATED change detection, in addition to the built-in handling (scrapedAt, the 'N ago' display times and the detail-fetch flag, the repost flags and the applicant numbers (numApplicants, applicantCountLabel, applicantVolumeLabel, resumePercentage, coverLetterPercentage, which grow while an ad is live) already never trigger a false UPDATED, and neither do companyOpenJobs, a link built from companyName, and salaryCurrency, a currency read from the pay text). The field stays in the output row either way - this only controls whether a change to it alone counts as a real change. Use a plain name for a top-level field (e.g. 'companyLogo'), or a dotted path to target one nested value inside a raw block without ignoring the whole block (e.g. 'companyProfileRaw.reviewsSummary.overallRating.value').
mcpConnectorsarrayOptionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON, the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).
notionParentPageUrlstringURL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.
maxNotifyListingsintegerCap on items written to each connector per run. Does not affect the dataset.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

titleTitle (text)
companyNameCompany (text)
locationLabelLocation (text)
salaryLabelSalary (text)
listingDateDisplayListed (text)
listingDateListed (date) (date)
workArrangementDisplayTextArrangement (text)
companyRatingCo. rating (text)
urlURL (link)
changeTypeChange (Incremental mode) (text)
idJob ID (text)
teaserTeaser (text)
Show 55 more fields
jobHookJob hook (text)
abstractAbstract (text)
contentcontent
contentTextFull description (text) (text)
contentMarkdownFull description (Markdown) (text)
contentSectionscontentSections
bulletPointsBullet points (array)
employerQuestionsScreening questions (array)
hasRoleRequirementsHas role requirements (boolean)
detailFetchedDetail fetched (boolean)
descriptionTruncatedDescription truncated (boolean)
companyIdcompanyId
companyUrlCompany profile URL (link)
companyNameSlugcompanyNameSlug
companyIndustryIndustry (text)
companySizeSize (text)
companyWebsiteWebsite (link)
companySpecialitiesSpecialities (array)
companyPrimaryLocationHead office (text)
companyLogocompanyLogo
companyCoverImagecompanyCoverImage
companyReviewCountReview count (number)
companySalaryRatingSalary rating (number)
companyPerksPerks & benefits (array)
companyAwardsAwards (array)
isPrivateAdvertiserPrivate advertiser (boolean)
salarysalary
salaryMinMin (number)
salaryMaxMax (number)
salaryPeriodPeriod (text)
numApplicantsApplicants (number)
applicantCountLabelApplicant count label (text)
applicantVolumeLabelApplication volume (text)
resumePercentage% with resume (number)
coverLetterPercentage% with cover letter (number)
recruiterProfilerecruiterProfile
nameRecruiter name (text)
slugslug
profileUrlRecruiter profile URL (link)
photoUrlphotoUrl
ratingRating (number)
reviewCountReview count (number)
placementCountPlacements (number)
contactNumberContact number (text)
agencyNameAgency (text)
agencySlugagencySlug
agencyWebsiteAgency website (link)
locationLocation (object)
specialisationsSpecialisations (array)
changedFieldsChanged fields (array)
firstSeenAtFirst seen (date)
lastSeenAtLast seen (date)
previousSeenAtPreviously seen (date)
isRepostRepost (boolean)
repostOfIdRepost of job ID (text)

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "id": "80123456",
  "url": "https://www.seek.com.au/job/80123456",
  "applyLink": "https://www.seek.com.au/job/80123456/apply",
  "title": "Software Engineer",
  "teaser": "Join a growing engineering team building customer-facing products.",
  "companyName": "Sample Company",
  "companyId": "123456",
  "companyUrl": "https://www.seek.com.au/companies/sample-company-123456",
  "advertiserName": "Sample Company",
  "advertiserId": "987654",
  "locationLabel": "Sydney, NSW",
  "classifications": [
    {
      "id": "6281",
      "label": "Information & Communication Technology",
      "subId": "6290",
      "subLabel": "Developers/Programmers"
    }
  ],
  "workTypes": [
    "Full time"
  ],
  "workArrangementLabels": [
    "Hybrid"
  ],
  "salaryLabel": "$120,000 - $140,000 per year + super",
  "salaryMin": 120000,
  "salaryMax": 140000,
  "salaryPeriod": "annual",
  "salaryCurrency": "AUD",
  "listingDate": "2026-04-17T01:53:13Z",
  "listingDateDisplay": "2d ago",
  "expiresAt": "2026-05-14T14:00:00.000Z",
  "isExpired": false,
  "status": "Active",
  "isVerified": true,
  "isFeatured": true,
  "displayType": "promoted",
  "bulletPoints": [
    "Hybrid working",
    "Career progression",
    "Modern tech stack"
  ],
  "companyOverview": "Sample Company builds software for retail and logistics customers across Australia.",
  "companyIndustry": "Information Technology",
  "companySize": "201-500 employees",
  "companyWebsite": "https://www.example-employer.com.au/",
  "companyRating": 3.3,
  "companyReviewCount": 81,
  "companyPerks": [
    "Flexible hours",
    "Learning budget"
  ],
  "companyLogo": "https://image-service-cdn.seek.com.au/sample-logo",
  "phoneNumbers": [
    "0491 570 156"
  ],
  "emails": [
    "recruiter@example.com"
  ],
  "isLinkOut": false,
  "detailFetched": true,
  "scrapedAt": "2026-04-20T00:40:05.202399+00:00"
}

Ways to use this data

  • Job board aggregators: feed AU and NZ listings with full detail into your own site or app.
  • Recruitment and sourcing: search by classification, work type and salary band to find roles matching a candidate profile.
  • Compensation benchmarking: collect parsed salary ranges across a classification or location to build a pay band dataset.
  • Employer research: pull company profiles, ratings and perks alongside their open roles.
  • Market monitoring: schedule a search with Incremental mode and get only new or changed listings.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does SEEK Jobs Scraper return?

The documented output for SEEK Jobs Scraper includes title, company, location, salary, listed, listed (date), arrangement and co. rating. Availability of each field depends on the source page and the selected mode.

How much does SEEK Jobs Scraper cost?

It costs $1.40 per 1,000 results on the Apify Free plan and from $0.70 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Can I get only new or changed jobs on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared jobs, and unchanged ones are not billed unless you turn on emitUnchanged.

Why does URL mode ignore my filter fields?

URL mode reads its filters from each pasted URL's path and query string, so the keyword, location, classification and other filter fields above are ignored to avoid conflicting instructions. The run log lists exactly what was dropped. To use the filter fields instead, set Mode to Search.

Why do I get about 550 jobs at most from one search?

SEEK itself serves at most 25 pages (about 550 jobs) of any single search, however many jobs match. When a search matches more than that, the run log says so with the match count. To cover everything, split the search: add Locations (locationsList), Keywords (keywordsList), a classification or sub-classification, a work type or a date range, or paste several URLs. Incremental mode never marks jobs EXPIRED after a search that hit this ceiling, because the jobs outside the window were not looked at.

Does it cover Singapore, Hong Kong, Malaysia, Indonesia, the Philippines or Thailand?

No. This actor covers SEEK Australia and New Zealand. SEEK's other markets run on the JobStreet and Jobsdb sites; see the JobStreet scraper in the related-scrapers block below.

Ready to collect with SEEK Jobs Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.