# Remote Jobs API & Scraper – Jobicy, Remote OK, Only New (`far003/remote-jobs-feed`) Actor

Remote jobs from sources licensed for commercial republishing (Jobicy, Remote OK). Deduplicated, yearly salary, filters, only-new mode. Pay per new job.

- **URL**: https://apify.com/far003/remote-jobs-feed.md
- **Developed by:** [Francesco Antonio Russo](https://apify.com/far003) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 new remote jobs

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Remote Jobs API & Scraper – Jobicy, Remote OK, Only New

**Remote job postings from sources that allow commercial republishing - Jobicy and Remote OK - in one clean feed. Unlike feeds built on boards whose terms bar passing jobs on (Himalayas, for example: "Do not pass them on to third parties ... including through feeds"), every source here is used within its published terms, with attribution built into each row. Same fields whatever the source, duplicates merged, salary normalized to a yearly figure, and an "only new" mode that makes a daily job feed a two-click job. You pay $0.001 per NEW job delivered - nothing for duplicates, jobs you already got, or jobs your filters drop.**

Built for people who need remote jobs as *data*: job-board and newsletter owners, recruiters watching a niche, career coaches, salary researchers, and anyone feeding a Slack channel, a Google Sheet, an n8n / Make / Zapier flow or an AI agent with fresh remote openings.

### What you get

- **Two public job boards, one schema.** Jobicy (the last 7 days, ~1,100 postings at the time of writing) and Remote OK (~100 current postings). Both are read through their public APIs: no scraping, no login, no proxy.
- **Duplicates merged.** The same posting on both boards (same company + title, or same link) is delivered once, with the other listing under `alsoListedOn`.
- **Only new postings.** Switch on `onlyNew` and every run returns just what appeared since the last one. The memory is stored in your Apify account, saved *after* each delivered batch, and can be split per task with `memoryKey`.
- **Salary you can compare.** Hourly, daily, weekly and monthly figures become a yearly figure, and the row says whether that figure was `salaryYearlyEstimated`. Currencies are kept as published (never converted).
- **Real filters.** Keywords (any of, whole words), excluded keywords, category, contract type, experience level, allowed countries or regions, only with salary, minimum yearly salary, posted after.
- **Honest labels.** Seniority that is only a guess from the title is flagged (`seniorityInferred`). A bare "Remote" is `unspecified`, never silently "worldwide".
- **No personal data.** Company and posting data only. No recruiter field is extracted. The description is the employer's own text and may still mention a name; e-mail addresses in it, including disguised ones such as `name(at)domain.com`, are replaced by `[email removed]`.
- **Attribution built in.** Every row carries the posting `url` on its source board and an `attribution` text, as the sources' terms require.

### Pricing - pay per new job

| Event | Price | When it is charged |
| --- | --- | --- |
| `job` - Remote job posting | **$0.001** | Once for each posting delivered to your dataset (after it is stored). |

**Free:** postings merged as duplicates, postings dropped by your filters, postings already delivered in an earlier run (`onlyNew`), postings a source could not give us, and a source that failed. If you set a **maximum cost per run**, the Actor stops delivering the moment the limit is reached and tells you in the `SUMMARY` how many postings it held back (with `onlyNew` they stay "new" for the next run). Example: 150 new postings = $0.15. A full unfiltered first run of ~1,200 postings = about $1.20.

### Quick start

1. Open the Actor and press **Start**: you get up to 25 current remote jobs (the prefilled `maxItems`).
2. Add filters, for example `keywords: ["python", "django"]`, `countries: ["DE"]`, `onlyWithSalary: true`.
3. For a daily feed: set `onlyNew: true`, remove `maxItems`, and **Schedule** the Actor once a day. Every run returns only the postings you have not seen.

### Input

| Field | Title | Default | What it does |
| --- | --- | --- | --- |
| `sources` | Sources | `["jobicy", "remoteok"]` | Which boards to read. Both are public APIs that need no key. Leave both selected for the widest feed; duplicates between them are merged. |
| `keywords` | Keywords (any of) | *empty* | Keep a posting if ANY of these words or phrases appears as a whole word in its title, company, tags or description ("java" does not match "javascript"). Leave empty for no keyword filter. |
| `excludeKeywords` | Exclude keywords | *empty* | Drop a posting if any of these appears. Same whole-word rule as above. |
| `keywordsInTitleOnly` | Match keywords in the title only | `false` | Look for the keywords in the job title only, not in the description. Fewer, more precise results. |
| `categories` | Categories | *empty* | Keep only these categories. Every posting gets one shared category whatever its source calls it. Leave empty for all. |
| `employmentTypes` | Contract types | *empty* | Keep only these. Postings whose source does not state a type (most of Remote OK) are left out when you pick one. |
| `seniorities` | Experience levels | *empty* | Keep only these. Jobicy publishes a level; for Remote OK it is guessed from the title (see seniorityInferred). Postings with no level are left out when you pick one. |
| `countries` | Allowed countries | *empty* | Keep postings someone living in one of these countries can take. Use ISO codes (US, DE), names (Germany) or regions (Europe, EU, EMEA, APAC, LATAM, North America). Worldwide postings are kept too (see below). The sources do not publish time zones, so there is no time-zone filter. |
| `includeWorldwide` | Include worldwide postings | `true` | With "Allowed countries" set, also keep postings that say "Anywhere" or "Worldwide". |
| `includeUnspecifiedLocation` | Include postings with no usable location | `false` | With "Allowed countries" set, also keep postings whose location is empty, a bare "Remote" or a city we cannot place. Off by default: we do not guess. |
| `onlyWithSalary` | Only postings with a salary | `false` | Drop postings that publish no salary. |
| `minSalaryYearly` | Minimum yearly salary | *empty* | Keep postings whose top yearly salary reaches this amount, in the currency below (hourly, weekly and monthly figures are converted to a year first). Postings with no salary or in another currency are dropped. Leave empty for no minimum. |
| `salaryCurrency` | Currency for the minimum | `USD` | Three-letter code of the currency the minimum is in. Currencies are never converted. |
| `postedAfter` | Posted after | *empty* | Only postings published on or after this date, such as 2026-10-15, or a relative time such as "3 days" or "2 weeks". |
| `descriptionFormat` | Description format | `text` | Plain text (easy to read and search), the original HTML (safe to sanitize before showing it), or no description (smaller output). E-mail addresses are removed either way. |
| `maxItems` | Maximum new postings | *empty* | Stop after this many postings are delivered (and charged). Postings held back stay "new" for the next run when "Only new postings" is on. Leave empty for no limit. The spending limit you set on the run is respected too. |
| `onlyNew` | Only new postings | `false` | Deliver only postings this feed has not delivered before. Run it on a schedule and every run returns just what appeared since. The memory is saved after each delivered batch. First run: everything currently listed counts as new. |
| `memoryKey` | Memory key | `default` | Name of the memory used by "Only new postings". Use a different key for each scheduled task (for example one per filter set) so they do not share what was delivered. Letters, digits, - and \_. |

Postings that do not pass the filters are dropped **for free**. All filters apply together. A posting whose source does not state the thing you filter on (for example a contract type) is left out when you filter on it.

### Output

One row per posting, always the same fields in the same order:

```json
{
  "id": "jobicy:153777",
  "source": "jobicy",
  "sourceName": "Jobicy",
  "url": "https://jobicy.com/jobs/153777-sales-manager-net-new-sales",
  "title": "Sales Manager - Net New Sales",
  "company": "CoderPad",
  "postedAt": "2026-10-22T04:45:25.000Z",
  "employmentTypes": ["full_time"],
  "seniority": "lead_director",
  "seniorityInferred": false,
  "category": "sales",
  "locationText": "USA",
  "locationRestriction": "restricted",
  "countries": ["US"],
  "salaryMin": 200000,
  "salaryMax": 220000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salaryMinYearly": 200000,
  "salaryMaxYearly": 220000,
  "salaryYearlyEstimated": false,
  "alsoListedOn": [],
  "attribution": "Jobicy (https://jobicy.com) - listing and apply link are on Jobicy; used under the Jobicy API terms.",
  "fetchedAt": "2026-10-22T10:08:37.000Z"
}
```

(shortened: the real row also has `description`, `companyLogoUrl`, `categories`, `tags` and `regions`.)

| Field | Type | Meaning |
| --- | --- | --- |
| `id` | string | Stable ID of the posting: "<source>:<id on that source>". Use it to join runs. |
| `source` | string | Board the record comes from: "jobicy" or "remoteok". When the same posting is on both, the first one in the list above supplies the record. |
| `sourceName` | string | Human name of the source board. |
| `url` | string | Canonical URL of the posting ON THE SOURCE board. Use it for the "Apply" button: the sources require that apply links and credit stay on their own pages. |
| `title` | string | Title as published. |
| `company` | string | Hiring company name. Company only: no recruiter names or e-mails are ever delivered. |
| `companyLogoUrl` | string/null | Company logo URL when the source gives one (the Remote OK logo itself is never used). |
| `postedAt` | string/null | Publication date, ISO 8601 UTC. |
| `description` | string/null | Job description as plain text (default), HTML or null, see "descriptionFormat". E-mail addresses inside the text are replaced by "\[email removed]". |
| `employmentTypes` | array | Any of full_time, part_time, contract, freelance, internship, temporary, other. Empty when the source does not say. |
| `seniority` | string/null | entry, mid, senior or lead_director. Null when the source says "any" or nothing and the title gives no hint. |
| `seniorityInferred` | boolean | True when seniority was guessed from the title because the source gives no level (always the case for Remote OK). |
| `category` | string | One shared category: engineering, devops, data, security, design, product, marketing, sales, support, finance, hr, legal, operations, healthcare, education or other. |
| `categories` | array | Category names exactly as the source gives them (Jobicy industries). Empty for Remote OK. |
| `tags` | array | Skill and topic tags as the source gives them (Remote OK). Empty for Jobicy. |
| `locationText` | string/null | The location text of the source, untouched. |
| `locationRestriction` | string | "worldwide" (the text says anywhere/worldwide), "restricted" (named countries or regions) or "unspecified" (nothing usable; a bare "Remote" is unspecified, not worldwide). |
| `countries` | array | ISO 3166-1 alpha-2 codes of the countries named in the location text. |
| `regions` | array | Regions named in the location text: europe, eu, emea, apac, latam, north america, americas. |
| `salaryMin` | number/null | Lower end of the published range, in the published period. Null when no salary is published. |
| `salaryMax` | number/null | Upper end of the published range. |
| `salaryCurrency` | string/null | ISO 4217 code. Never converted: no exchange rates are applied. |
| `salaryPeriod` | string/null | year, month, week, day or hour. |
| `salaryMinYearly` | number/null | Lower end per year: x12 for months, x52 weeks, x260 days, x2080 hours. Same currency as salaryCurrency. |
| `salaryMaxYearly` | number/null | Upper end per year. |
| `salaryYearlyEstimated` | boolean/null | False when the source published a yearly figure; true when the yearly figure was computed from another period (or a guessed one). Null without salary. |
| `alsoListedOn` | array | Same posting found on the other source: \[{ source, sourceName, id, url }]. Empty when only one source has it. |
| `attribution` | string | Credit text for the source(s). Show it, with the posting URL, wherever you display the posting. |
| `fetchedAt` | string | When the source was read, ISO 8601 UTC (up to one hour old: sources are read at most once per hour). |

#### Salary: how the yearly figure is made

| Published period | Yearly figure | `salaryYearlyEstimated` |
| --- | --- | --- |
| year | as published | `false` |
| month | x 12 | `true` |
| week | x 52 | `true` |
| day | x 260 | `true` |
| hour | x 2,080 | `true` |

Remote OK publishes yearly USD amounts; the few figures under 1,000 there are clearly hourly rates, so they are read as hourly and flagged as estimated. Some sources publish odd numbers (for example a range of 10,000-10,000): they are passed on as published. **Currencies are never converted** - there is no exchange-rate source, so `minSalaryYearly` compares in one currency (`salaryCurrency`, default USD) and leaves out the others.

#### Location: what it means

`locationRestriction` is `worldwide` when the posting says Anywhere / Worldwide, `restricted` when it names countries or regions (`countries` are ISO codes, `regions` are europe, eu, emea, apac, latam, north america, americas), and `unspecified` when there is nothing usable: an empty location, a bare "Remote", or a city we do not place. We do not guess. **Time zones are not published by these sources, so there is no time-zone field or filter.**

#### The run summary

Every run writes a `SUMMARY` record to the key-value store: status, what each source returned (`fetched`, `usable`, `discarded`, whether it came from the one-hour cache), how many postings were merged as duplicates, dropped by each filter, already delivered, delivered and held back, the stop reason, billing, and warnings.

### Sources and their terms (read on 22 October 2026)

| Source | What the terms say | What this Actor does |
| --- | --- | --- |
| **Jobicy** - [API & RSS terms](https://jobicy.com/jobs-rss-feed), [site terms](https://jobicy.com/terms) | Listings may be used in your own products, commercially, and stored, cached, processed and redistributed. "Use of content requires a clickable source link"; keep the canonical Jobicy URL and keep apply links pointing at Jobicy; credit Jobicy. "Start a new automated pass no more than once per hour"; handle HTTP 429 with a deferred retry. The API serves the last 7 days. | Uses the public API only. Keeps the Jobicy URL and an `attribution` on every row. Reads Jobicy **at most once per hour** (the last answer is cached for 60 minutes), waits at least 1 second between requests and obeys `Retry-After`. |
| **Remote OK** - [API notice](https://remoteok.com/api), [site terms](https://remoteok.com/legal) | The API answer says: link back to the URL on Remote OK and mention Remote OK as a source; do not use the Remote OK logo; otherwise API access can be suspended. The site terms say nothing against API reuse. | Keeps the Remote OK URL and an `attribution` on every row, never ships the Remote OK logo, same one-hour cache and 1-request-per-second pacing. |

**Your side of the deal:** if you publish these postings, show the `attribution` and link to the posting `url` (for Remote OK a normal followed link), and send applicants to that URL. Jobicy also asks you to **remove postings that have expired** (a posting that drops out of its 7-day feed is not necessarily closed: confirm before you mark it closed), and to keep your own data in step with the source. The terms of each board apply to you as the user of the data.

The `attribution` texts delivered in the rows are exactly:

- Jobicy: `Jobicy (https://jobicy.com) - listing and apply link are on Jobicy; used under the Jobicy API terms.`
- Remote OK: `Remote OK (https://remoteok.com) - source of this listing; link back to the Remote OK URL.`

#### Sources deliberately NOT used (and why)

- **Himalayas** - its API terms (section 113, read 22 Oct 2026) allow showing jobs "only on sites and apps you operate" and say "Do not pass them on to third parties ... including through feeds". A data feed sold to other people is exactly that, so it is not included.
- **Arbeitnow** - its API asks for a link back, but its terms of use (section 2) grant a licence for "personal, non-commercial transitory viewing only" of the site materials, and it is unclear whether that covers a paid feed. Left out until Arbeitnow confirms in writing that commercial reuse is fine.
- **Remotive** - API terms ask you not to submit its jobs to third-party sites, require a 24-hour delay and a link back, and offer a paid API for other uses; not used.
- **Working Nomads** - its API is open but no reuse terms are published for it; no terms, no use.
- **LinkedIn, Indeed and any site that blocks bots** - never scraped.

### Limits (honest)

- Two boards, not twenty. Together about 1,200 postings are listed at any time; most are tech, sales and operations roles. Jobicy only serves the **last 7 days**.
- Sources are read **at most once per hour**; a run started twice in an hour sees the same data (`fetchedAt` tells you when it was read).
- Category and seniority are mapped by rules: Jobicy states a level, but it is dropped when the title contradicts it (many Jobicy postings are tagged "Director" whatever the title says), and for Remote OK the level is always a guess from the title. Check `seniorityInferred`.
- The description is the employer's text. We remove e-mail addresses but do not rewrite it.
- No contact details, no application tracking, no salary currency conversion, no time zones.
- A posting that disappears from a board is not announced; use `postedAt` and `onlyNew`.

### FAQ

**How is "only new" decided?** A posting is "delivered" once it is in your dataset. Its id (and the id of the same posting on the other board) is then saved to a memory in your account. The next run skips any posting whose id is in the memory. Postings are forgotten after 60 days.

**Can I run several scheduled tasks with different filters?** Yes - give each task its own `memoryKey`, so they do not share the memory.

**What if a run is interrupted?** The Apify platform may restart a run on another server. The Actor reads what is already in the dataset and does not deliver or charge those postings twice.

**Why did my second run return nothing?** With `onlyNew` that is the point: nothing new appeared. Without it, check the filters and the `SUMMARY`.

**Can I use my own keys or another job board?** Not in this version. Open an issue in the Actor page with the board and we will check its terms.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/far003~remote-jobs-feed/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["python"], "countries": ["DE"], "onlyNew": true, "memoryKey": "python-de"}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("far003/remote-jobs-feed").call(run_input={"onlyNew": True, "memoryKey": "daily", "categories": ["engineering"]})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["company"], job["url"], job["attribution"])
```

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('far003/remote-jobs-feed').call({ onlyNew: true, memoryKey: 'daily' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Works with Apify **Schedules** (run it every morning), **webhooks** (call your endpoint when a run finishes), the Make, Zapier and n8n integrations, Google Sheets, Slack and the Apify MCP server for AI agents. Export the dataset as JSON, CSV, Excel, XML or RSS.

### Support

Something wrong, or a field you need? Use the **Issues** tab of this Actor. Include the run ID; the `SUMMARY` record tells us what each source returned.

# Actor input Schema

## `sources` (type: `array`):

Which boards to read. Both are public APIs that need no key. Leave both selected for the widest feed; duplicates between them are merged.

## `keywords` (type: `array`):

Keep a posting if ANY of these words or phrases appears as a whole word in its title, company, tags or description ("java" does not match "javascript"). Leave empty for no keyword filter.

## `excludeKeywords` (type: `array`):

Drop a posting if any of these appears. Same whole-word rule as above.

## `keywordsInTitleOnly` (type: `boolean`):

Look for the keywords in the job title only, not in the description. Fewer, more precise results.

## `categories` (type: `array`):

Keep only these categories. Every posting gets one shared category whatever its source calls it. Leave empty for all.

## `employmentTypes` (type: `array`):

Keep only these. Postings whose source does not state a type (most of Remote OK) are left out when you pick one.

## `seniorities` (type: `array`):

Keep only these. Jobicy's level is used unless the title contradicts it; for Remote OK, and when Jobicy's level looks wrong, it is guessed from the title (see seniorityInferred). Postings with no level are left out when you pick one.

## `countries` (type: `array`):

Keep postings someone living in one of these countries can take. Use ISO codes (US, DE), names (Germany) or regions (Europe, EU, EMEA, APAC, LATAM, North America). Worldwide postings are kept too (see below). The sources do not publish time zones, so there is no time-zone filter.

## `includeWorldwide` (type: `boolean`):

With "Allowed countries" set, also keep postings that say "Anywhere" or "Worldwide".

## `includeUnspecifiedLocation` (type: `boolean`):

With "Allowed countries" set, also keep postings whose location is empty, a bare "Remote" or a city we cannot place. Off by default: we do not guess.

## `onlyWithSalary` (type: `boolean`):

Drop postings that publish no salary.

## `minSalaryYearly` (type: `integer`):

Keep postings whose top yearly salary reaches this amount, in the currency below (hourly, weekly and monthly figures are converted to a year first). Postings with no salary or in another currency are dropped. Leave empty for no minimum.

## `salaryCurrency` (type: `string`):

Three-letter code of the currency the minimum is in. Currencies are never converted.

## `postedAfter` (type: `string`):

Only postings published on or after this date, such as 2026-10-15, or a relative time such as "3 days" or "2 weeks".

## `descriptionFormat` (type: `string`):

Plain text (easy to read and search), the original HTML (safe to sanitize before showing it), or no description (smaller output). E-mail addresses are removed either way.

## `maxItems` (type: `integer`):

Stop after this many postings are delivered (and charged). Postings held back stay "new" for the next run when "Only new postings" is on. Leave empty for no limit. The spending limit you set on the run is respected too.

## `onlyNew` (type: `boolean`):

Deliver only postings this feed has not delivered before. Run it on a schedule and every run returns just what appeared since. The memory is saved after each delivered batch. First run: everything currently listed counts as new.

## `memoryKey` (type: `string`):

Name of the memory used by "Only new postings". Use a different key for each scheduled task (for example one per filter set) so they do not share what was delivered. Letters, digits, - and \_.

## Actor input object example

```json
{
  "sources": [
    "jobicy",
    "remoteok"
  ],
  "keywords": [
    "react",
    "node.js"
  ],
  "excludeKeywords": [
    "intern"
  ],
  "keywordsInTitleOnly": false,
  "countries": [
    "DE",
    "Italy"
  ],
  "includeWorldwide": true,
  "includeUnspecifiedLocation": false,
  "onlyWithSalary": false,
  "minSalaryYearly": 80000,
  "salaryCurrency": "USD",
  "postedAfter": "3 days",
  "descriptionFormat": "text",
  "maxItems": 100,
  "onlyNew": false,
  "memoryKey": "default"
}
```

# Actor output Schema

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

No description

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

No description

# 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 = {
    "sources": [
        "jobicy",
        "remoteok"
    ],
    "keywordsInTitleOnly": false,
    "includeWorldwide": true,
    "includeUnspecifiedLocation": false,
    "onlyWithSalary": false,
    "salaryCurrency": "USD",
    "descriptionFormat": "text",
    "maxItems": 25,
    "onlyNew": false,
    "memoryKey": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("far003/remote-jobs-feed").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 = {
    "sources": [
        "jobicy",
        "remoteok",
    ],
    "keywordsInTitleOnly": False,
    "includeWorldwide": True,
    "includeUnspecifiedLocation": False,
    "onlyWithSalary": False,
    "salaryCurrency": "USD",
    "descriptionFormat": "text",
    "maxItems": 25,
    "onlyNew": False,
    "memoryKey": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("far003/remote-jobs-feed").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 '{
  "sources": [
    "jobicy",
    "remoteok"
  ],
  "keywordsInTitleOnly": false,
  "includeWorldwide": true,
  "includeUnspecifiedLocation": false,
  "onlyWithSalary": false,
  "salaryCurrency": "USD",
  "descriptionFormat": "text",
  "maxItems": 25,
  "onlyNew": false,
  "memoryKey": "default"
}' |
apify call far003/remote-jobs-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,far003/remote-jobs-feed"
        }
    }
}
```

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/cpjQNXBcNsZhfyChA/builds/GUI3C9BtbR9gKAUco/openapi.json
