RemoteOK Jobs Scraper at a glance
RemoteOK Jobs Scraper is a ready-to-run Apify actor from abotapi for collecting jobs data. Its documented output includes job id, title, company, location and posted, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $2.20 per 1,000 results on the Apify Free plan and from $1.50 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, Lead Generation, Developer Tools
- Pricing
- $2.20 per 1,000 results (Free plan), from $1.50 on paid plans
- Output
- Documented below · JSON, CSV, Excel
- Inputs
- 29 options
Scrape RemoteOK jobs by keyword or job URL. Extract title, company, location, remote details, tags, salary when available, listing URL, description, and metadata into clean structured dataset rows.
What RemoteOK Jobs Scraper can do
- Two ways to find jobs. Keyword search across current listings, or paste RemoteOK listing and tag URLs directly. No need to build search URLs by hand.
- Salary, company, location, age and tag filters. Narrow a run to exactly the roles you care about before you pay for a row.
- Normalized fields on every row. Salary midpoint, posting age in days, a cleaned plain-text description, and matched search tokens, in addition to the site's own fields.
- Client-side sorting. Order saved rows by posting time, salary, or company name without a second pass.
- Optional raw fields. Keep the complete original listing object alongside the normalized ones, or drop it to save space.
- Optional MCP connector export. Pipe a summary of saved jobs into apps such as Notion, Linear, Airtable, or Apify.
Choose what to collect
These inputs let you configure RemoteOK Jobs Scraper - Remote Listings, Salaries & Details. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring | Use keyword search to filter current listings by terms, or URL mode to read one or more RemoteOK listing URLs directly. |
searchTermsarray | Enter job keywords or tag phrases such as python or senior+devops. Use all jobs for a broad default run. Each term is processed separately and capped by Max items. |
startUrlsarray | Paste RemoteOK URLs: tag listings, the homepage or /api feed, company pages, job pages and location pages (job, company and location pages return rows only when they match a job in the current feed), with optional ?tags= ?location= ?search= ?page= ?order_by= facets. Each URL is processed separately and capped by Max items. Unsupported URLs are skipped with a warning. |
tagsarray | Keep only jobs whose tag list contains at least one of these values. |
companiesarray | Keep only jobs whose company name contains one of these values. |
locationsarray | Keep only jobs whose location text contains one of these values. |
minSalaryinteger | Keep only jobs whose salary range reaches at least this amount. |
Show 22 more inputs
| Input | What it controls |
|---|---|
maxSalaryinteger | Keep only jobs whose salary range starts at or below this amount. |
postedWithinDaysinteger | Keep only jobs posted within this many days. Leave empty for no age filter. |
sortBystring | Client-side sort order applied after filtering. |
requireSalaryboolean | Keep only jobs where a salary range is present. |
keywordFilterstring | Keep only jobs whose title, company, location, description or tags contain at least one of these comma-separated keywords (case-insensitive). Applied after the search terms. |
includeUnverifiedboolean | Turn off to keep only listings that RemoteOK marks as verified. |
filterNonTechboolean | Keep only technical roles: the job title must name an engineering, developer, devops, data, security, QA or similar role. Sales, recruiting, marketing, support and coordinator roles are dropped even when RemoteOK tags them with technology words. |
includeDescriptionTextboolean | When enabled, the actor adds a cleaned plain-text version of the listing description. |
includeRawFieldsboolean | When enabled, the actor keeps the full original job object alongside normalized fields. |
maxItemsinteger | Maximum matching rows to save for each search term or start URL. This is a cap, not a guarantee. |
maxResultsinteger | Alias of Max items. When set above 0 it replaces Max items; 0 means unlimited (every matching job). Leave empty to use Max items. |
maxPagesinteger | Leave empty to walk every result page. When a source has more matching jobs than fit in one page, the actor keeps paginating until Max items is reached or the source is exhausted. |
resumeFromRunIdstring | Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Jobs already collected there (matched by id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. |
incrementalModeboolean | For scheduled runs. Remembers the jobs seen by the previous run with the same tracked scope (or the same State key) and delivers only NEW, UPDATED and REAPPEARED jobs, each tagged with changeType, changedFields, firstSeenAt and lastSeenAt. Unchanged jobs are not delivered or billed unless 'Also deliver unchanged jobs' is on. Leave off for a normal run. Different from 'Resume from a previous run', which continues one specific run. |
stateKeystring | Optional name for the incremental baseline. Leave empty to derive it automatically from your search terms, URLs and filters, so differently configured runs never share a baseline. Set the same text on two runs to make them share one. Only used when Incremental mode is on. |
emitUnchangedboolean | When Incremental mode is on, also push jobs that did not change since the last run (changeType UNCHANGED). Each delivered row is billed like any other row, and EXPIRED rows come in addition to the Max items cap. Off by default. |
emitExpiredboolean | When Incremental mode is on, push a row with changeType EXPIRED for each job tracked last run that is no longer in the feed. Only when the run covered the whole tracked scope: a run capped by Max items, with a failed or skipped search, or starting past page 1 never reports expiry. Each delivered row is billed like any other row, and EXPIRED rows come in addition to the Max items cap. Off by default. |
ignoreFieldsForChangesarray | Field names to leave out of change detection in incremental mode (dotted paths allowed for nested fields). scrapedAt, scraped_at and postedAgeDays are always ignored. Example: tags. |
mcpConnectorsarray | Optionally send scraped jobs into 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 summary per job; the full record stays in the dataset. Leave empty to skip. Supported: Notion, Linear, Airtable, and Apify. |
notionParentPageUrlstring | URL or id of the Notion page under which job pages are created. Required for Notion export; ignored by other connectors. |
maxNotifyJobsinteger | Cap on jobs written to each connector. Does not affect the dataset. |
maxNotifyListingsinteger | Same cap as 'Max jobs to export per connector'. When set, this value wins. 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.
jobIdJob IDtitleTitlecompanyNameCompanylocationTextLocationpostedAtPostedsalary_minSalary Minsalary_maxSalary MaxtagsTagsurlListing URL (link)applyUrlApply URL (link)searchTermSearch TermsourceTypeModeShow 1 more field
scrapedAtScrapedExample output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"id": "1000001",
"jobId": "1000001",
"slug": "remote-senior-backend-engineer-sample-labs-1000001",
"title": "Senior Backend Engineer",
"position": "Senior Backend Engineer",
"company": "Sample Labs",
"companyName": "Sample Labs",
"location": "Remote, Worldwide",
"locationText": "Remote, Worldwide",
"descriptionText": "We are a fully remote team looking for a senior backend engineer to join our platform team.",
"tags": [
"python",
"backend",
"senior"
],
"tagCount": 3,
"url": "https://remoteok.com/remote-jobs/remote-senior-backend-engineer-sample-labs-1000001",
"applyUrl": "https://remoteok.com/remote-jobs/remote-senior-backend-engineer-sample-labs-1000001",
"sourceUrl": "https://remoteok.com/remote-python-jobs",
"sourceType": "search-term",
"searchTerm": "python",
"postedAt": "2024-01-15T09:00:00+00:00",
"postedEpoch": 1705309200,
"postedAgeDays": 12,
"salary_min": 90000,
"salary_max": 130000,
"salaryMid": 110000,
"hasSalary": true,
"companyLogoUrl": "https://remoteok.com/assets/sample-logo.png",
"scrapedAt": "2024-01-27T10:00:00.000Z",
"scraped_at": "2024-01-27T10:00:00.000Z",
"source": "remoteok",
"source_url": "https://remoteok.com/remote-jobs/remote-senior-backend-engineer-sample-labs-1000001",
"company_name": "Sample Labs",
"company_slug": "sample-labs",
"company_url": "https://remoteok.com/company/sample-labs",
"company_logo_url": "https://remoteok.com/assets/sample-logo.png",
"type": null,
"work_mode": "remote",
"experience_level": null,
"currency": "USD",
"salary_period": "year",
"markets": [
"python",
"django"
],
"posted_at": "2024-01-15T09:00:00+00:00",
"expires_at": null,
"data_source": "remoteok-api",
"data_source_url": "https://remoteok.com/api",
"verified": true,
"matchedSearchTokens": [
"python"
],
"matchedTagFilters": [],
"raw": {}
}Ways to use this data
- Recruiting and sourcing: pull current remote roles by keyword, salary band, or tag to build candidate outreach lists.
- Job board and job-alert apps: feed filtered, sorted listings into your own site, bot, or notification tool.
- Market and compensation research: track salary ranges, posting volume, and tag trends for remote roles over time.
- Lead generation: find companies actively hiring in a given location or stack, using the company and tag filters.
- Competitive and industry analysis: monitor which companies and roles a segment of the remote job market is posting.
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 RemoteOK Jobs Scraper return?
The documented output for RemoteOK Jobs Scraper includes job id, title, company, location, posted, salary min, salary max and tags. Availability of each field depends on the source page and the selected mode.
How much does RemoteOK Jobs Scraper cost?
It costs $2.20 per 1,000 results on the Apify Free plan and from $1.50 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.
Why did a search term or URL return fewer jobs than I expected within a mixed run?
A job counts as handled only after it has been saved. Search terms or URLs that stop at their Max items cap do not hide the rest of that page from later terms or URLs in the same run. A later term or URL still skips jobs that an earlier one in the same run already saved, so overlapping terms return each job once. Jobs that do not pass your filters never count as handled. Resume from a previous run only skips jobs actually found in the prior run's dataset.
Can I get only new job listings on a schedule?
There is no built-in change-detection mode. For a recurring pull, pass the previous run's ID (or dataset ID) into Resume from a previous run: this run then skips every job id saved in that one run and appends the rest. It does not remember runs before that one, so a job saved two runs ago can be saved again. For a clean recurring feed, de-duplicate by id on your side. You also have to pass the latest run ID into the next run's input yourself.
Why did my run fail instead of returning an empty dataset?
The run stops with a clear error when no search terms or URLs are supplied, when Resume from a previous run points to a run or dataset your account cannot read, when every pasted URL is unsupported, or when no results page could be loaded at all (see the messages under Plan Requirement). If only some search terms or URLs fail to load, the run logs a warning, saves the rest, and lists the failed ones in the OUTPUT summary. Check the URLs, then run it again.
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 saved jobs into Notion, Linear or Airtable.
