SimplyHired $1๐Ÿ’ฐ URL | Keyword Filters | Enriched avatar

SimplyHired $1๐Ÿ’ฐ URL | Keyword Filters | Enriched

Pricing

from $1.00 / 1,000 results

Go to Apify Store
SimplyHired $1๐Ÿ’ฐ URL | Keyword Filters | Enriched

SimplyHired $1๐Ÿ’ฐ URL | Keyword Filters | Enriched

From $1/1K. Pull active SimplyHired jobs across the US, UK, Canada, Australia, Ireland, and India. Search via builder or URL. Extract 40+ fields, including title, company, salary range, full HTML description, qualifications, geocoordinates, and apply URL.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

0

Monthly active users

2 days ago

Last modified

Share

SimplyHired Jobs Scraper: Titles, Salaries, Full Descriptions & Apply Links

SimplyHired Jobs Scraper turns SimplyHired into a clean job-postings API. Get job title, company, employer rating, parsed salary range (min, max, currency, period), city, state, latitude/longitude, work setting, qualifications, benefits, the full HTML job description and the SimplyHired apply link for active listings across the US, UK, Canada, Australia, Ireland and India sites. Build a search from keywords, location, job type and country, or paste any simplyhired.com /search or /job URL, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • 40+ fields per job ad, including a parsed salary range (min, max, currency, period), city, state, latitude/longitude, work setting, qualifications, benefits and the full HTML description, not just the 10 to 15 fields typical scrapers return.
  • Two ways to search: build with keywords, location, job type and country site, or paste any simplyhired.com /search URL and the scraper walks pagination forward from there, or a /job URL for that single listing.
  • Six regional SimplyHired sites in one input field: United States, United Kingdom, Canada, Australia, Ireland and India.
  • Concurrent detail-page enrichment with per-record delivery, so a mid-page failure still keeps the listings already fetched instead of losing the whole page.
  • Client-side de-duplication across pages and searches by the canonical listing id, with the listing budget split evenly across multiple keywords in one run.
  • Automatic retry across proxy connection tiers when one is refused, with a clear log warning (not a silently wrong result) when the actual cause is your own proxy setup.
  • Built for schedules: Incremental mode returns only new and changed listings on recurring runs, and Resume continues one interrupted run without re-collecting what it already saved.

Use Cases

  • Job boards and aggregators: pull fresh SimplyHired listings by keyword and location to mirror or enrich your own job feed.
  • Recruiter and sourcing tools: track new postings for target companies or roles as soon as they appear, and pull only what changed on a schedule.
  • Compensation research: build salary-range datasets by title, location and job type from the parsed salaryMin / salaryMax fields.
  • Labor market analytics: measure posting volume, remote-vs-onsite mix and qualifications trends across regions and countries.
  • Application tooling: collect the SimplyHired apply link and full job description text to feed an autofill, alerting or matching tool.

Data You Get

Sample shape: values are illustrative placeholders, not from a live ad.

FieldExample
id"abcd1234example"
url"https://www.simplyhired.com/job/abcd1234example"
title / displayTitle"Software Engineer" / "Software Engineer, Backend"
company"Sample Company Inc"
companyRating4.2
companyPageUrl"https://www.simplyhired.com/company/000-sample-company-inc"
location / formattedLocation"New York, NY"
city / state"New York" / "NY"
latitude / longitude40.7128 / -74.006
country"us"
jobTypes / workSettings["Full-time"] / ["Hybrid"]
salary"$140,000 - $180,000 a year"
salaryMin / salaryMax140000 / 180000
salaryCurrency / salaryPeriod"USD" / "year"
descriptionHtml / descriptionTextfull HTML job description / the same description as plain text
qualifications["Bachelor's degree", "5+ years experience"]
benefits["Health insurance", "401(k)"]
skillsAll["Python", "AWS", "API design"]
datePosted"2026-09-20T08:00:00.000Z"
applyUrlthe SimplyHired apply link, a redirect that forwards to the employer's application page (the token rotates on every fetch)
sponsoredfalse
source"SimplyHired"
changeType (incremental mode only)"NEW" (also "UPDATED", "UNCHANGED", "REAPPEARED", "EXPIRED")

Each record also carries normalizedTitle (a lowercased title for matching), employerLogoUrl and employerHomepage, remoteAttributes (SimplyHired's own remote-work tags), the raw compensation object behind the parsed salary fields, a short snippet preview, a requirements list distinct from qualifications, datePostedEpochMs and dateOnIndeed (millisecond timestamps), mobileApplyUrl alongside applyUrl, indeedApply / auction / expired flags, jobCardTrackingKey (SimplyHired's own per-render analytics key), the jobTypeRequested / searchQuery / searchLocation / pageNumber that produced the row, and scrapedAt. In incremental mode, changedFields, firstSeenAt and lastSeenAt are added alongside changeType.

How to Use

  1. Pick a mode: search (build with keywords, location, job type and country) or url (paste one or more simplyhired.com links).
  2. For search mode, fill in keywords, location, country site and job type. For URL mode, paste any /search or /job URL; the search-builder fields above are ignored.
  3. Set Max listings (and optionally Max pages) to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search by keyword and location:

{
"mode": "search",
"queries": ["software engineer"],
"location": "Remote",
"country": "us",
"jobType": "fulltime",
"maxPages": 5,
"maxListings": 100,
"fetchDetails": true
}

Multiple keywords, sponsored cards skipped, SERP-only fields for a fast and cheap feed:

{
"mode": "search",
"queries": ["nurse", "physical therapist", "medical assistant"],
"location": "Boston, MA",
"country": "us",
"jobType": "any",
"skipSponsored": true,
"maxListings": 150,
"fetchDetails": false
}

URL mode on the UK site, mixing a search link and a single job link:

{
"mode": "url",
"urls": [
"https://www.simplyhired.co.uk/search?q=product+manager&l=London",
"https://www.simplyhired.com/job/abcd1234example"
],
"maxPages": 5,
"maxListings": 200,
"fetchDetails": true
}

Recurring monitoring (scheduled daily run, only what changed):

{
"mode": "search",
"queries": ["software engineer"],
"location": "Remote",
"country": "us",
"maxListings": 0,
"fetchDetails": true,
"incrementalMode": true,
"emitExpired": true
}

Schedule this same input to run daily. The first run returns everything as NEW. Later runs return only NEW, UPDATED and EXPIRED listings (plus REAPPEARED once a listing that was previously marked EXPIRED shows up again), not the full result set every time.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/simplyhired-com-scraper").call(run_input={
"mode": "search",
"queries": ["software engineer"],
"location": "Remote",
"country": "us",
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], job["company"], job["salary"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/simplyhired-com-scraper').call({
mode: 'search',
queries: ['software engineer'],
location: 'Remote',
country: 'us',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Max pages, Max listings and the per-keyword budget

Max pages caps how many SERP pages are walked per search entry (or per pasted URL); each page returns up to 20 listings. Leave it empty to walk every page until the site's own end-of-results signal. Max listings caps the total across every search in the run; set it to 0 for no cap. When a run has multiple keywords, the Max listings budget is split evenly across them so one keyword can't crowd out the others.

Resume and recurring updates

Two different things, both under one input section, so they don't get confused:

  • Resume from a previous run (resumeFromRunId) continues one specific interrupted run. Paste the ID of a previous run (or its dataset), and this run skips every listing id already saved there, appending only new ones. Good for an unbounded pull (maxPages left empty, maxListings: 0) that got cut off.

  • Incremental mode (incrementalMode) is for recurring monitoring of the SAME search (for example, scheduled daily). Turn it on and the actor remembers the previous run's results itself, no run or dataset id to paste. Each listing in the output then gets a changeType:

    • NEW: never tracked before for this search.
    • UPDATED: tracked before, but at least one non-volatile field changed since last time (see changedFields). Per-request tracking tokens such as applyUrl are ignored so they never trigger a false UPDATED.
    • UNCHANGED: identical to last time. Only emitted (and billed) when emitUnchanged is on; off by default.
    • EXPIRED: was tracked as present in a previous run, and was not found in this one. Only produced when emitExpired is on and this run reached the natural end of results for every tracked search, with no maxListings cap hit and no resumeFromRunId. A capped, blocked or resumed run cannot tell "gone" apart from "not reached yet", so it leaves the previous state untouched instead of guessing.
    • REAPPEARED: a listing marked EXPIRED in an earlier run that has now been found again. This can only happen for a listing that some earlier run actually marked absent, which itself only happens when that earlier run had emitExpired on and completed a full, uncapped, non-resumed scan of the tracked search. If emitExpired has never been on, or every run so far was capped, blocked, or used resumeFromRunId, no listing is ever marked absent, so REAPPEARED cannot occur, no matter how many times a listing actually disappears and comes back.

    State is tracked separately per query/location/country/jobType/skipSponsored/URL-set/fetchDetails combination, or under one shared campaign if you set stateKey, so two differently-configured runs never mix baselines.

Independently of both, a checkpoint is saved automatically as the run progresses. If the run is interrupted by an Apify platform migration or you click Resurrect on a failed run, it picks back up in the same run without re-saving, or re-charging for, listings it already collected. No input is needed for this; it's automatic.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape; the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify โ†’ Settings โ†’ Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (use the builder fields below) or url (paste SimplyHired URLs).
queriesarrayno default (prefill: ["software engineer"])One scrape per keyword. Leave empty to browse without a keyword filter.
locationstringno default (prefill: Remote)City, state, ZIP, or "Remote". Leave empty to search nationwide.
countrystringusWhich SimplyHired regional site to query: us, uk, ca, au, ie, in.
jobTypestringanyany / fulltime / parttime / contract / temporary / internship / commission.
skipSponsoredbooleanfalseDrop sponsored / promoted job cards. Applied client-side, in both modes.
urlsarrayno default (prefill: a sample search URL)URL mode only. A /search URL is paged forward independently; a /job URL returns that one listing. Search-builder fields above are ignored.
maxPagesintegerno default (empty = unlimited)Max SERP pages per search (or per pasted URL). Each page returns up to 20 listings. Leave empty to walk every result page until the site's own end-of-results signal.
maxListingsinteger20Stop after this many listings across all searches. 0 = no cap.
fetchDetailsbooleantrueAlso fetch each job's detail page for the full HTML description, qualifications list, employer logo, lat/lng and apply URL.
resumeFromRunIdstringno default (empty)A previous run ID or dataset ID to continue one specific interrupted run. Listings already collected there (matched by id) are skipped.
incrementalModebooleanfalseTurn on for daily or recurring monitoring of the same search. See "Resume and recurring updates" above.
stateKeystringno default (empty)Incremental mode only. Names the monitoring campaign so its state stays stable, or lets you deliberately share state across differently-configured runs. Leave empty to derive a key automatically from the query/location/URL and detail settings.
emitUnchangedbooleanfalseIncremental mode only. Also return (and bill) listings that haven't changed, marked UNCHANGED.
emitExpiredbooleanfalseIncremental mode only. Also return (and bill) listings from a previous run that are no longer found, marked EXPIRED. Only produced after a run that fully scanned the tracked search.
proxyobjectno default (prefill: Apify Residential, country US)SimplyHired requires residential routing pinned to the country site you query; datacenter exit IPs are rejected. For other regional sites, change the country to match (GB / CA / AU / IE / IN).
mcpConnectorsarrayno default (empty)Optional: send a summary of each listing to apps you authorized under Integrations.
notionParentPageUrlstringno default (empty)Notion connector only: page under which listing pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live ad. changeType, changedFields, firstSeenAt and lastSeenAt are only added when incrementalMode is on; a normal run's output shape below is unchanged.

{
"id": "abcd1234example",
"url": "https://www.simplyhired.com/job/abcd1234example",
"title": "Software Engineer",
"displayTitle": "Software Engineer, Backend",
"normalizedTitle": "software engineer",
"company": "Sample Company Inc",
"companyRating": 4.2,
"companyPageUrl": "https://www.simplyhired.com/company/000-sample-company-inc",
"employerLogoUrl": "https://logos.example-cdn.com/sample-company-inc.png",
"employerHomepage": "https://www.samplecompany.example",
"location": "New York, NY",
"formattedLocation": "New York, NY",
"city": "New York",
"state": "NY",
"latitude": 40.7128,
"longitude": -74.006,
"country": "us",
"jobTypes": ["Full-time"],
"workSettings": ["Hybrid"],
"remoteAttributes": [],
"salary": "$140,000 - $180,000 a year",
"salaryMin": 140000,
"salaryMax": 180000,
"salaryCurrency": "USD",
"salaryPeriod": "year",
"compensation": { "currency": "USD", "period": "year" },
"snippet": "Short listing preview text appears here...",
"descriptionHtml": "<p>Full long-form HTML description appears here.</p>",
"descriptionText": "Full long-form description as plain text appears here.",
"requirements": ["Python", "AWS"],
"qualifications": ["Bachelor's degree", "5+ years experience"],
"benefits": ["Health insurance", "401(k)"],
"skillsAll": ["Python", "AWS", "API design"],
"datePosted": "2026-09-20T08:00:00.000Z",
"datePostedEpochMs": 1789891200000,
"dateOnIndeed": 1789891200000,
"applyUrl": "https://www.simplyhired.com/out?r=sampletoken000",
"mobileApplyUrl": "https://www.simplyhired.com/m/out?r=sampletoken000",
"indeedApply": false,
"sponsored": false,
"auction": false,
"expired": false,
"jobCardTrackingKey": "0-pdx0-0-0000000000000000-0000000000000000",
"jobTypeRequested": "fulltime",
"searchQuery": "software engineer",
"searchLocation": "New York, NY",
"pageNumber": 1,
"source": "SimplyHired",
"scrapedAt": "2026-09-29T12:00:00.000Z"
}

Plan Requirement

This scraper requires residential proxy routing pinned to the country site you query; SimplyHired rejects most datacenter exit IPs. The prefilled proxy setting in the Console uses the residential group, and the actor automatically retries with a different connection tier when one is refused. If your plan doesn't include residential proxy access, paste your own residential proxy URLs into the Proxy field under Proxy.

FAQ

How much does it cost?

You pay per listing returned, with an optional surcharge when detail pages are fetched (the default). The Pricing tab shows the current rates. Use Max listings to cap the cost of any run.

This actor collects only publicly available job listing data. You are responsible for how you use it: follow SimplyHired's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution.

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

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated listings, and unchanged ones are not billed unless you turn on Emit unchanged. Turn on Emit expired to also get EXPIRED listings after a run completes a full, uncapped scan; REAPPEARED appears only after such a run has marked a listing expired.

Why do my keyword and location filters have no effect?

Search-builder fields (queries, location, jobType) only apply when mode is search. In url mode, the scraper follows whatever filters are already baked into the pasted URL and ignores the builder fields entirely, since two different filter sources for the same run would conflict.

Why did my run return zero listings instead of failing?

If SimplyHired refuses every request on every proxy tier this actor tries, the run does not guess: it finishes with a warning in the log and an empty dataset, so you are not billed for a page that was never actually read. Check the log for the specific reason and try again in a few minutes, or supply your own residential proxy URLs. The run fails outright when it can detect a configuration problem immediately, such as an unreadable resumeFromRunId, turning on Incremental mode together with resumeFromRunId while a monitoring baseline already exists for that search, or the proxy configuration itself failing to set up.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

๐Ÿ”— Want more jobs data?

Pair this actor with these related scrapers from the same team:

๐Ÿ’ผ ZipRecruiter Scraper
From $1/1K. Scrape ZipRecruiter jobs with titles, companies, salaries, locations...
๐Ÿ’ผ Jobs.cz
Scrape Czech job listings from Jobs.cz. Search builder (keyword, location, field, salary...
๐Ÿ’ผ Jora Jobs Scraper
Scrape Jora.com job listings across supported countries by keyword, filters, or URL...
๐Ÿ’ผ SEEK Jobs Scraper
From $0.7/1K. Scrape SEEK.com.au and SEEK.co.nz jobs by keyword, location, or filters...
๐Ÿ’ผ JobStreet Scraper
From $1/1K. Scrape JobStreet listings across Malaysia, Singapore, Indonesia, and the...
๐Ÿ’ผ NIJobs Scraper
Scrape NIJobs.com listings across Northern Ireland by keyword, location, salary, posted...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support

  • ๐Ÿž Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • ๐Ÿ› ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.