SimplyHired Scraper at a glance
SimplyHired Scraper is a ready-to-run Apify actor from abotapi for collecting jobs data. Its documented output includes id, change type (incremental mode), url, title and company, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.50 per 1,000 results on the Apify Free plan and from $1.00 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, Automation, Developer Tools
- Pricing
- $1.50 per 1,000 results (Free plan), from $1.00 on paid plans
- Output
- Documented below · JSON, CSV, Excel
- Inputs
- 27 options
Scrape active SimplyHired jobs across the US, UK, Canada, Australia, Ireland and India from $1/1K listings. Search by filters or URL. Extract 40+ fields including job titles, companies, salary ranges, full HTML descriptions, qualifications, coordinates and apply URLs.
What SimplyHired Scraper can do
- 40+ fields per job ad. Includes 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 sites. One input field covers United States, United Kingdom, Canada, Australia, Ireland and India.
- Detail enrichment. 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.
- No duplicates. 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.
- Connection fallback. Automatic retry across several connection routes when one is challenged or refused, and a clear failure message (never a silently empty result) when no page could be read.
Choose what to collect
These inputs let you configure SimplyHired Scraper - Jobs, Salaries & Company Details. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring · required | Search mode = pick keywords + location + filters below. URL mode = paste any simplyhired.com /search or /job URL refined in your browser. |
queriesarray | Free-text search terms (e.g. "software engineer", "nurse", "data analyst"). One scrape per keyword. Leave empty to search by location only; a search needs a keyword or a location. |
locationstring | City, state, ZIP, or "Remote". Examples: "New York, NY", "Boston, MA", "94103", "Remote". Leave empty to search nationwide (a keyword is then required). |
countrystring | Which SimplyHired regional site to query. The site language follows the host. Defaults to the US site. |
jobTypestring | Filter by employment scope. "Any" walks the unfiltered SERP. |
skipSponsoredboolean | Drop sponsored / promoted job cards. Applied as a client-side filter. |
datePostedstring | Only jobs posted within this window. Sent to the site as a native filter in Search mode and also applied to each row's post date on this side. |
Show 20 more inputs
| Input | What it controls |
|---|---|
minSalaryinteger | Only jobs whose listed minimum pay is at least this yearly amount (hourly, weekly and monthly pay is annualised; jobs with no listed pay are dropped). Sent to the site as a native filter in Search mode and also checked on this side. 0 = off. |
remoteOnlyboolean | Keep only jobs flagged remote. Applied on this side to each listing. |
sortBystring | SimplyHired ignores its own sort parameters, so 'Newest first' orders the listings of each fetched page by post date on this side; it does not re-order across pages. |
keywordstring | Single-keyword alias for the Keywords field, accepted so runs built for other SimplyHired scrapers keep working. Ignored when Keywords is filled. |
results_wantedinteger | Alias for Max listings. Used when Max listings is left unset or still at its default of 20; a Max listings value you changed yourself takes priority. |
max_pagesinteger | Alias for Max pages per search, used only when that field is empty. |
urlsarray | One or more simplyhired.com URLs (also the .co.uk.ca.com.au.ie and .co.in sites). Supported: keyword + location search, keyword-only, location-only, paged (pn), job-type filtered (jt), search with a job= preselect, and a single /job page. Each search URL pages forward independently. Only the keyword, location, job type and start page come from the pasted URL; the Date posted, Minimum yearly salary, Remote only, Sort by and Skip sponsored fields above are still applied on this side to the results of every URL, so clear them if you want the pasted search unfiltered. |
startUrlsarray | Alias for the Search URLs field. When filled it replaces the sample Search URLs, and when no keywords are given the run switches to URL mode automatically. A Search URLs list you edited yourself takes priority. |
maxPagesinteger | How many SERP pages to walk per query × location combination (or per pasted URL). Each page returns up to 20 listings. Leave empty to walk every result page. Use maxListings in tandem to cap the total budget across all searches. |
maxListingsinteger | Stop after this many listings across all searches. 0 = no cap. |
fetchDetailsboolean | When ON, also fetch each job's detail page for the full HTML description, qualifications list, employer logo, lat/lng, and apply URL. SERP cards already carry id, title, company, location, snippet, and posted date, so simple feeds work fine with this OFF. Default ON for richer output. |
resumeFromRunIdstring | Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already collected there (matched by id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. For recurring daily monitoring of the same search, use Incremental mode below instead. |
incrementalModeboolean | Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. A listing counts as UPDATED when any returned field other than the ignored ones changes (title, company, location, salary, job type, description, qualifications, benefits and so on); ignored by default and never compared: scrapedAt, applyUrl, mobileApplyUrl, jobCardTrackingKey, pageNumber and auction (they change with every scrape), plus jobKey, summary, skills, jobType and sourceSearchUrl (copies or derivations of compared fields: id, snippet or descriptionText, skillsAll, jobTypes and your search inputs, so a real change still shows through the source field). A plain field name is ignored at any depth, including inside nested objects (see Ignore fields when detecting changes to add more). Turn on "Emit unchanged" or "Emit expired" only when you also want those listings returned (and billed). State is kept separately for each query/location/URL and detail-mode setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above. |
stateKeystring | Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the query/location/URL and detail settings, different searches then never mix state with each other. |
emitUnchangedboolean | Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want the full snapshot every run. |
emitExpiredboolean | Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max listings capped it or when Resume was used. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking. |
ignoreFieldsForChangesarray | Optional. Field names that must not make a listing count as UPDATED, in addition to the built-in ignored fields. A plain name (for example employerLogoUrl) is ignored at any depth; a dotted path (for example compensation.min) ignores exactly that nested field. The fields are still returned in the output, just never compared. Leave empty to use the defaults. |
mcpConnectorsarray | Optionally 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). |
notionParentPageUrlstring | URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListingsinteger | Cap 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.
idIDchangeTypeChange type (incremental mode) (text)urlURL (link)titleTitlecompanyCompanycompanyRatingRatingcityCitystateStatelatitudeLatlongitudeLngsalarySalarysalaryMinMin PayShow 17 more fields
salaryMaxMax PaysalaryPeriodPeriodjobTypesTyperemoteAttributesRemote / settingdatePostedPostedapplyUrlApply (link)skillsAllSkillsqualificationsQualificationsbenefitsBenefitssponsoredSponsoredchangedFieldsChanged fields (incremental mode) (array)firstSeenAtFirst seen (incremental mode) (date)lastSeenAtLast seen (incremental mode) (date)scrapedAtScrapeddescriptionTextDescriptionrequirementsRequirementssalaryCurrencyCurrencyExample output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"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"
}Ways to use this data
- 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.
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 SimplyHired Scraper return?
The documented output for SimplyHired Scraper includes id, change type (incremental mode), url, title, company, rating, city and state. Availability of each field depends on the source page and the selected mode.
How much does SimplyHired Scraper cost?
It costs $1.50 per 1,000 results on the Apify Free plan and from $1.00 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 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.
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.
