# We Work Remotely Jobs Lookup (`accountable_eel/weworkremotely-jobs-lookup`) Actor

Fetch We Work Remotely's own per-category RSS feeds and get one clean row per posting: title, company, region, employment type, headquarters, posted date, link and full description. No login, no API key, official feeds only. You pay per posting returned, and an empty category feed costs nothing.

- **URL**: https://apify.com/accountable\_eel/weworkremotely-jobs-lookup.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 job posting returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## We Work Remotely Jobs Lookup

You name a category — `programming`, `design`, `customer-support`, or `all` for the combined feed —
and this actor fetches We Work Remotely's own RSS feed for it and returns one clean row per posting:
title, company, region, employment type, company headquarters, posted date, a permanent link and the
full job description. No login, no API key, no scraping of rendered pages — every field comes
straight out of WWR's official RSS, the same feed a browser or an RSS reader gets.

### Who it's for

The accountable\_eel catalogue sells company and hiring intelligence columns for outbound and
recruiting. Each actor takes a list of identifiers and returns one flat, stably-named row per
result: the shape a Clay table, an n8n workflow, or an AI agent can consume without
post-processing. Pricing is pay-per-event: a fraction of a cent for a posting you actually got, and
nothing at all for a category that comes back empty. No seat licence, no monthly minimum, no credit
system to decode.

This actor is the "curated boards" corner of the catalogue's remote-jobs coverage, alongside
`remotive-jobs-lookup` and `himalayas-jobs-lookup` — three independent official sources for the same
niche, in case one board is thin on a given role or you just want a wider net. It sits next to the
ATS lookups (`greenhouse-jobs-lookup`, `lever-jobs-lookup` and friends) that answer "what is *this
company* hiring for" — this one answers "what's currently open in *this category*, anywhere".

### Why this one

- **The RSS feed already has everything.** WWR's per-category feed carries the full job description
  in every item, not just a title and a link — so there is no second per-posting request to make,
  no extra hop to pay for, and no risk of a detail page changing shape under you.
- **The description comes back as text, not raw markup.** WWR escapes each posting's HTML into the
  feed rather than wrapping it in CDATA, and a few characters are escaped twice over. Both are
  decoded and the markup is stripped before the description reaches you — `description` reads as
  plain text, never as a page of `&lt;p&gt;` tags.
- **The boilerplate is separated out, not left sitting in the text.** Every posting opens with a
  "Headquarters: ..." line and closes with a "To apply: `<link>`" paragraph. The headquarters line
  becomes its own `headquarters` field; the apply paragraph is dropped, since it only ever repeats
  the same link already sitting in the row's own `link` field.
- **You are never billed for the same posting twice.** WWR's "programming" feed is a superset of
  `full-stack-programming` / `front-end-programming` / `back-end-programming`, and the `all` feed is
  a superset of every category — request several overlapping category lines in one run and, by
  default, each posting is still counted and charged exactly once.
- **Twelve categories, curl-verified one at a time.** Every category slug this actor accepts was
  checked with a live request on 2026-08-24 (200, real `<item>` entries) — nothing here is a slug
  guessed from a URL pattern and left untested. A category that doesn't resolve tells you so, with
  the full list of ones that do, instead of silently returning nothing.

### What you get

One row per job posting by default. (Turn off "One row per job posting" in the Input tab to get one
row per *category* instead, with the whole posting list nested in `jobs`.)

| Field | Type / format | Description |
| --- | --- | --- |
| `query` | text | The category line you passed in, unchanged. |
| `found` | boolean | `true` if the category resolved to a real feed. `false` rows are never charged. |
| `status` | text | `OK`, `BAD_FORMAT` (not a recognised category), or `BLOCKED`. |
| `categoryQueried` | text | The category slug actually fetched, after normalizing what you typed. |
| `categoryLabel` | text | The category's human-readable label, e.g. "Customer Support". |
| `jobCount` | number | How many postings this category returned after your filters — this is exactly what you're charged for. |
| `truncated` | boolean | `true` if more postings were available than "Most postings to return per category" allowed. |
| `jobs` | array | The full posting list. Present in every row; it's what gets expanded into separate rows in "one row per posting" mode. |
| `title` | text | Job title, with the company name split off. |
| `companyName` | text | Hiring company, read from the "Company: Job Title" format WWR uses in every posting's title. |
| `category` | text | This specific posting's own WWR category — useful when you queried `all` or an aggregate like `programming`, since it can hold postings from several sub-categories. |
| `region` | text | Where WWR says the role can be worked from, e.g. "Anywhere in the World", "USA Only". |
| `country` / `state` | text | Present on newer postings only; empty string on older ones rather than missing. |
| `skills` | array | Comma-separated skill tags WWR attaches to some postings, e.g. `["Figma"]`. Empty array when WWR doesn't tag any. |
| `type` | text | Employment type, e.g. "Full-Time" — present on newer postings only. |
| `headquarters` | text | The company's stated headquarters, read out of the posting's own "Headquarters:" line. |
| `postedAt` | date (ISO) | The posting date, converted from WWR's RSS `pubDate`. |
| `link` | link | Permanent link to the posting on weworkremotely.com. |
| `guid` | text | WWR's own posting identifier — stable, and what deduplication keys on. |
| `logoUrl` | image | Company logo image URL, when WWR includes one. |
| `description` | text | The full posting text, as plain text — HTML stripped, entities decoded, headquarters line and apply-link paragraph removed. |
| `descriptionSnippet` | text | The first ~320 characters of `description`, cut at a word boundary. |
| `scrapedAt` | date (ISO) | When this actor fetched the row. |

A category that isn't recognised comes back as a single `found: false` row naming the categories
that are, and is never charged.

### Pricing

- **Job posting returned**: $1 per 1,000 job postings

Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (`found:false`) are never charged.

You're charged **per posting returned**, not per category — a category that returns 12 postings
costs twelve, a category that returns none costs nothing, and an unrecognised category line costs
nothing. Because you pay per posting, "Most postings to return per category" is your budget control.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `categories` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~weworkremotely-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"categories":["programming","design","customer-support"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

One category per line — `programming`, `full-stack-programming`, `front-end-programming`,
`back-end-programming`, `devops-sysadmin`, `design`, `customer-support`, `sales-and-marketing`,
`product`, `management-and-finance`, `all-other`, or `all` (also what a blank line means). Common
shorthand works too — `devops`, `frontend`, `sales`, `support` all resolve to the right feed.

**🎯 Narrow the results** — applied here, to the postings after they arrive, since WWR's RSS has no
query parameters of its own to filter by:

| Input | What it does |
| --- | --- |
| `maxJobsPerQuery` | Most postings to return per category. Default 200. |
| `titleKeywords` | Keep only titles containing one of these — `["engineer","designer"]`. |
| `excludeTitleKeywords` | Drop titles containing one of these — `["intern","senior"]`. Applied after the include list. |
| `companyKeywords` | Keep only postings from companies whose name contains one of these. |
| `regionKeywords` | Keep only postings whose region contains one of these — e.g. `["USA"]`, `["Europe"]`. |
| `skipDuplicateJobs` | On by default. Each posting is returned, and billed, once per run even if two category lines overlap. |

### Input

```json
{
  "categories": [
    "programming",
    "design",
    "customer-support"
  ]
}
```

One category per line — e.g. "programming", "design", "customer-support", "sales-and-marketing". Leave a line blank, or write "all", for the combined feed of every category. Accepted formats: programming, design, all.

### Output

| query | found | status | categoryQueried | categoryLabel | jobCount | truncated | jobs | title | companyName | category | region | country | state | skills | type | headquarters | postedAt | link | guid | logoUrl | description | descriptionSnippet | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| programming | true | OK | programming | Programming (all) | 25 | false | \<all postings found (full list)> | Python Backend Development Talent with RAG and Agentic AI Experience | Toptal | Full-Stack Programming | Asia Only |  |  | \[] |  |  | 2026-08-12T18:38:32.000Z | https://weworkremotely.com/remote-jobs/toptal-python-backend-development-talent-with-rag-and-agentic-ai-experience | https://weworkremotely.com/remote-jobs/toptal-python-backend-development-talent-with-rag-and-agentic-ai-experience |  | Headquarters:

Summary:
We are seeking an experienced Python Backend Developer to design, build, and deploy scalable AI-powered applications using Retrieval-Augmented Generation, large language models, and agentic AI frameworks. The role will focus on delivering a production-grade RAG system and AI chatbot that can securely integrate with enterprise data, APIs, databases, and cloud services.
General information:
The organization is developing an AI-powered platform and requires an experienced individual contributor to build its RAG architecture and conversational AI capabilities. The developer will work closely with a distributed team and should be available for several hours of overlap with US working hours.
The project involves designing AI systems that go beyond basic prompt engineering, including multi-step workflows, autonomous agents, vector search, knowledge retrieval, memory management, and tool integration. The solution must be scalable, secure, observable, and suitable for production use.
The technology environment includes Python, FastAPI, large language models, LangGraph, LangChain, vector databases, Azure AI services, AWS, Docker, Kubernetes, and microservice-based architectures.
Task and deliverables:
Design the end-to-end architecture for a scalable RAG system and AI chatbot.
Develop Python backend services, REST APIs, and microservices using FastAPI or similar frameworks.
Build document ingestion, chunking, embedding, indexing, retrieval, and reranking pipelines.
Implement vector search solutions using Azure AI Search or comparable vector databases.
Design autonomous AI agents capable of planning, reasoning, tool usage, and decision-making.
Develop multi-step AI workflows using LangGraph, LangChain, CrewAI, AutoGen, or similar orchestration frameworks.
Integrate commercial and open-source LLMs, including Azure OpenAI, OpenAI, Anthropic Claude, Gemini, and comparable models.
Implement conversation memory, session management, context management, and agent collaboration patterns.
Connect AI workflows with APIs, databases, enterprise systems, and external tools.
Develop asynchronous, high-performance services capable of handling concurrent AI workloads.
Implement prompt management, structured outputs, guardrails, fallback logic, and model evaluation processes.
Establish logging, monitoring, tracing, observability, security, and error-handling standards.
Containerize and deploy AI services using Docker, Kubernetes, Azure, or AWS.
Translate business requirements into technical designs, delivery milestones, and production-ready AI solutions.
Collaborate with the wider team while independently owning architecture and implementation decisions.
Required experience:
Required: 8 or more years of professional Python backend development experience.
Required: Strong experience designing REST APIs, microservices, asynchronous services, and distributed backend systems.
Required: Hands-on experience building production-grade RAG applications.
Required: Strong understanding of embeddings, document chunking, semantic search, vector indexing, retrieval strategies, and reranking.
Required: Hands-on experience developing AI agents and multi-step LLM workflows.
Required: Experience with agentic AI frameworks such as LangGraph, LangChain, CrewAI, AutoGen, or comparable platforms.
Required: Experience integrating LLMs through OpenAI, Azure OpenAI, Anthropic Claude, Gemini, or open-source model APIs.
Required: Ability to design AI architecture beyond basic prompt engineering.
Required: Experience integrating AI applications with APIs, databases, data pipelines, and enterprise systems.
Required: Experience implementing security, monitoring, logging, tracing, and observability for production services.
Required: Experience deploying containerized applications using Docker and cloud platforms such as Azure or AWS.
Required: Ability to independently translate business requirements into scalable technical solutions.
Required: Strong communication and collaboration skills in a distributed working environment.
Required: Availability for several hours of overlap with US working hours. | Headquarters: Summary: We are seeking an experienced Python Backend Developer to design, build, and deploy scalable AI-powered applications using Retrieval-Augmented Generation, large language models, and agentic AI frameworks. The role will focus on delivering a production-grade RAG system and AI chatbot that can… | 2026-08-31T06:01:15.184Z |

A miss comes back as a row with `"found": false` and is never charged.

### Legal note

This actor reads **public data only** — We Work Remotely's own published RSS feeds, the same ones
any browser, RSS reader, or search engine can request without an account. It does not log in, does
not accept or store any WWR credential, and has no input field in which you could give it one.

It reads no private data — only what a hiring company chose to publish in its own job posting: the
role, the company, the region, and the posting text. It does not collect names, email addresses, or
contact details of individuals. You are responsible for how you use the results; check We Work
Remotely's own terms before putting heavy, scheduled use of this actor into production.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~weworkremotely-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"categories":["programming","design","customer-support"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~weworkremotely-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"categories":["programming","design","customer-support"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~weworkremotely-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"categories":["{{category}}"]}`, mapping the row's category into the `categories` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "We Work Remotely Jobs Lookup | Apify" — the agent will find and run this actor.

# Actor input Schema

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

One category per line — e.g. "programming", "design", "customer-support", "sales-and-marketing". Leave a line blank, or write "all", for the combined feed of every category. Accepted formats: programming, design, all. You're only charged for the ones we actually find — a miss costs nothing.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

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

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

## `maxResults` (type: `integer`):

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `maxJobsPerQuery` (type: `integer`):

WeWorkRemotely's feeds run from a handful of postings up to a couple hundred per category. You pay per posting returned, so this is also your budget control.

## `titleKeywords` (type: `array`):

Optional. Keep only postings whose title contains at least one of these words — e.g. "engineer", "designer". Case doesn't matter and partial words work. Leave empty to keep every posting.

## `excludeTitleKeywords` (type: `array`):

Optional. Drop any posting whose title contains one of these words — e.g. "intern", "senior". Applied after the include list above, so a title matching both is dropped.

## `companyKeywords` (type: `array`):

Optional. Keep only postings from companies whose name contains one of these — e.g. "Automattic", "GitLab". Partial matches work.

## `regionKeywords` (type: `array`):

Optional. Narrow by the region WeWorkRemotely prints on each posting — e.g. "USA", "Europe", "Anywhere".

## `skipDuplicateJobs` (type: `boolean`):

On by default. WeWorkRemotely's "programming" feed and the combined "all" feed both repeat postings from the more specific categories — with this on, each posting is returned, and billed, exactly once per run even if it matched several category lines.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `expandRows` (type: `boolean`):

When on, each job posting found gets its own row instead of being grouped under its category. You're still only charged once per category, no matter how many rows it produces.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## `proxyConfiguration` (type: `object`):

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "categories": [
    "programming",
    "design",
    "customer-support"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "maxJobsPerQuery": 200,
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "companyKeywords": [],
  "regionKeywords": [],
  "skipDuplicateJobs": true,
  "columns": [
    "categoryQueried",
    "categoryLabel",
    "jobCount",
    "truncated",
    "jobs",
    "title",
    "companyName",
    "category",
    "region",
    "country",
    "state",
    "skills",
    "type",
    "headquarters",
    "postedAt",
    "link",
    "guid",
    "logoUrl",
    "description",
    "descriptionSnippet"
  ],
  "expandRows": true,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "categories": [
        "programming",
        "design",
        "customer-support"
    ],
    "includeKeywords": [],
    "excludeKeywords": [],
    "titleKeywords": [],
    "excludeTitleKeywords": [],
    "companyKeywords": [],
    "regionKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/weworkremotely-jobs-lookup").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 = {
    "categories": [
        "programming",
        "design",
        "customer-support",
    ],
    "includeKeywords": [],
    "excludeKeywords": [],
    "titleKeywords": [],
    "excludeTitleKeywords": [],
    "companyKeywords": [],
    "regionKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/weworkremotely-jobs-lookup").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 '{
  "categories": [
    "programming",
    "design",
    "customer-support"
  ],
  "includeKeywords": [],
  "excludeKeywords": [],
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "companyKeywords": [],
  "regionKeywords": []
}' |
apify call accountable_eel/weworkremotely-jobs-lookup --silent --output-dataset

```

## MCP server setup

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

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/e3YMEjHvCnSuj9q2L/builds/vrpgvxTBo42dL1NvZ/openapi.json
