DEV Community

PennyData
PennyData

Posted on

Pull new We Work Remotely jobs into a CSV or Google Sheet with one API call

We Work Remotely publishes public RSS feeds per category, but each feed only holds the newest listings and the raw XML has no clean company, region or job-type fields. If you want a daily list of fresh remote roles you can sort in a sheet, you can parse the feeds yourself, or call a hosted actor that does it and returns tidy rows. Here is the second route, with working code.

1. The input

The actor is pennydata/wwr-remote-jobs-feed (Apify Store). It reads only the public RSS feeds, no login or key on the site side. Input fields (from its input schema):

{
  "categories": ["programming", "devops"],
  "keywords": ["python", "kubernetes"],
  "region": "Europe",
  "jobTypes": ["Full-Time", "Contract"],
  "postedWithinDays": 7,
  "includeDescription": false,
  "maxItems": 100
}
Enter fullscreen mode Exit fullscreen mode
  • categories: all, programming, full-stack, front-end, back-end, design, devops, customer-support, sales-marketing, management-finance, product, other.
  • keywords: a job is kept if ANY keyword appears in its title, company, category, skills or description.
  • region: text the region/country/state must contain (Anywhere, Europe, United States).
  • maxItems: hard cap on jobs, and on what you pay.

2. Run it and write a CSV

Get an Apify API token (Console, Settings, Integrations) and pip install requests.

import csv, os, requests

TOKEN = os.environ["APIFY_TOKEN"]
URL = "https://api.apify.com/v2/acts/pennydata~wwr-remote-jobs-feed/run-sync-get-dataset-items"

run_input = {
    "categories": ["programming", "devops"],
    "keywords": ["python", "kubernetes"],
    "postedWithinDays": 7,
    "includeDescription": False,
    "maxItems": 100,
}

r = requests.post(URL, params={"token": TOKEN}, json=run_input, timeout=280)
r.raise_for_status()
jobs = r.json()

cols = ["title", "company", "category", "jobType", "region", "postedAt", "expiresAt", "url"]
with open("wwr_jobs.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=cols, extrasaction="ignore")
    w.writeheader()
    w.writerows(jobs)
print(len(jobs), "jobs written")
Enter fullscreen mode Exit fullscreen mode

Import wwr_jobs.csv into Google Sheets (File, Import), or push rows with the Sheets API / gspread if you prefer. A 100-job run is a short call; for large pulls start the run with POST /v2/acts/.../runs and poll instead of run-sync (which times out after 300 seconds).

3. What a row looks like

This is the output example from the actor's README:

{
  "title": "Frontend Engineer, Ads",
  "company": "Reddit",
  "category": "Front-End Programming",
  "jobType": "Full-Time",
  "region": "Anywhere in the World",
  "skills": [],
  "postedAt": "2026-10-26T07:31:27.000Z",
  "expiresAt": "2026-11-25T07:31:27.000Z",
  "url": "https://weworkremotely.com/remote-jobs/reddit-frontend-engineer-ads"
}
Enter fullscreen mode Exit fullscreen mode

With includeDescription on (the default) each row also carries the plain-text description.

4. Keep it fresh

Each feed shows only recent listings, so run it on a schedule. In Apify Console, open the actor, save the input as a task, and add a Schedule (for example daily at 07:00). Pair it with a webhook or a small script that appends only URLs you have not seen, and you have a de-duplicated remote-jobs list for yourself or a niche job board.

Cost

See the actor page for current pay-per-event pricing. Filtered-out jobs, duplicates and failed feeds are not charged, and maxItems caps the bill. Listing text belongs to the posting companies, so link back to the original URL when you republish.

I built this and earn from its runs. Written with AI assistance (Claude).

Top comments (0)