DEV Community

Zebin Wang
Zebin Wang

Posted on

How to Export Remote Job Salary Data to CSV (Himalayas + Remote OK)

If you're job hunting remotely, or building anything around remote work, salary data is the part you actually want and the part that's hardest to collect. Two job boards publish it in a usable form: Himalayas (salary range, currency, period, and seniority) and Remote OK (salary range in USD, plus tags).

I built two small Apify Actors that turn those listings into clean rows. Here's how to get the salary data into a CSV and do something useful with it.

What each source gives you

Himalayas Remote Jobs Scraper
title, companyName, employmentType, seniority, minSalary, maxSalary, currency, salaryPeriod, isWorldwide, publishedAt, url

Remote OK Jobs Scraper
title, company, location, tags, salaryMinUsd, salaryMaxUsd, publishedAt, url

Himalayas is the better source when seniority matters and when you need to know whether a role is open worldwide (isWorldwide). Remote OK is handy when you want everything already in USD and filterable by tech tags.

Step 1: Run the scrapers

In the browser, open either Actor, click Try for free, fill in the input, and hit Start. Then export the results as CSV.

Or from Python:

pip install apify-client pandas
Enter fullscreen mode Exit fullscreen mode
from apify_client import ApifyClient
import pandas as pd

client = ApifyClient("YOUR_APIFY_TOKEN")

def run(actor_id, run_input):
    r = client.actor(actor_id).call(run_input=run_input)
    return list(client.dataset(r["defaultDatasetId"]).iterate_items())

himalayas = pd.DataFrame(run("slate_cyclone/himalayas-jobs-scraper",
    {"keywords": "python", "salaryRequired": True, "maxJobs": 100}))
remoteok = pd.DataFrame(run("slate_cyclone/remoteok-jobs-scraper",
    {"tags": ["python", "react"], "salaryRequired": True, "maxJobs": 100}))
Enter fullscreen mode Exit fullscreen mode

Step 2: Keep only rows with salary data

h = himalayas.dropna(subset=["minSalary", "maxSalary"])
r = remoteok.dropna(subset=["salaryMinUsd", "salaryMaxUsd"])
Enter fullscreen mode Exit fullscreen mode

Step 3: Answer real questions

Median salary range by seniority on Himalayas (yearly, USD only):

yearly_usd = h[(h["currency"] == "USD") & (h["salaryPeriod"].str.lower() == "year")]
print(yearly_usd.groupby("seniority")[["minSalary", "maxSalary"]].median())
Enter fullscreen mode Exit fullscreen mode

Only roles open worldwide:

print(h[h["isWorldwide"] == True][["title", "companyName", "minSalary", "maxSalary", "url"]])
Enter fullscreen mode Exit fullscreen mode

Remote OK salaries for a given tag, for example python:

py = r[r["tags"].apply(lambda t: "python" in [x.lower() for x in (t or [])])]
print(py[["title", "company", "salaryMinUsd", "salaryMaxUsd"]].describe())
Enter fullscreen mode Exit fullscreen mode

Step 4: Save it

h.to_csv("himalayas_salaries.csv", index=False)
r.to_csv("remoteok_salaries.csv", index=False)
Enter fullscreen mode Exit fullscreen mode

Cost

Both Actors are pay-per-result: $0.80 per 1,000 jobs.

Check the actual values in your own export before you rely on a filter. Salary periods and currencies vary by listing, so filter them explicitly, as above, rather than assuming everything is yearly USD.


This post was written with AI assistance.

Top comments (0)