Upwork Jobs Universal Scraper
Pricing
from $1.02 / 1,000 results
Upwork Jobs Universal Scraper
Stay on top of new Upwork jobs that match your search. Keyword, type, rate, skills and country filters, full description, budget and a direct job URL. No login. Pay per job.
Pricing
from $1.02 / 1,000 results
Rating
5.0
(1)
Developer
Scrapifier
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
Upwork Jobs Scraper
Stay on top of new Upwork jobs that match what you already search for. Type the same keywords you use on Upwork, add filters, or paste a search URL, and export every matching posting as JSON, CSV or Excel — or pull them from the API on a schedule.
⚡ For every job you get the title, the full description, hourly range or fixed budget, experience level, engagement length, required skills, posting time and a direct job URL. No Upwork login. You pay per job.
🎯 Why scrape Upwork jobs?
- Job alerts: sort by most recent, turn on “Only new jobs since last run”, schedule the Actor every 5–15 minutes, and feed Slack, email or your own board.
- Freelance market research: measure demand, rates and required skills for a query across countries.
- Lead lists: every new posting that matches your niche is an opportunity, with budget and description attached.
- AI / matching datasets: full plain-text descriptions at scale for classification or ranking models.
📊 What data does Upwork Jobs Scraper extract?
| Field | Description |
|---|---|
id, ciphertext | Upwork job id and the id used in the job URL |
url | Direct job page (https://www.upwork.com/jobs/~02…) |
title | Job title |
description | Full plain-text description (fullDescription on by default) |
jobType | HOURLY or FIXED |
experienceLevel | EntryLevel, IntermediateLevel or ExpertLevel |
hourlyRateMin, hourlyRateMax | Hourly budget bounds |
fixedBudget | Fixed-price amount |
durationWeeks | Engagement length in weeks |
hourlyEngagementType | Hourly engagement type when Upwork sets one |
skills, skillUids | Skill labels and Upwork skill ids |
publishedAt | Publication time (ISO 8601) |
searchInput | The search or pasted URL that produced this job |
This Actor reads the public job card (the same data you see before opening a job as a visitor). Client spend, payment-verified flags and proposal counts are not on that card and are not returned.
With flatten enabled, skills and skillUids become comma-separated strings so every CSV column stays flat.
🚀 How to scrape Upwork jobs
- Type your Search keywords (
python,react developer,logo design) and set Sort by to Most recent first for alerts. - Optionally filter: job type, experience level, client country, hourly/fixed budget, client hires, duration, workload, timezone, contract-to-hire, posted-within.
- Or paste full Upwork search URLs. Each URL is scraped with its own filters, on top of the keyword search.
- Set Maximum jobs (
0= every unique job this search returns) and click Start. - For a feed of new work only, enable Only new jobs since last run and put the Actor on a schedule.
- Open Storage to preview jobs and export JSON, CSV, Excel or XML, or read them from the dataset API.
📥 Input parameters
| Field | Key | Type | Default | Description |
|---|---|---|---|---|
| Search keywords | query | string | python (prefill) | What you would type on Upwork. Empty = the whole feed with the other filters. |
| Sort by | sort | select | recency | recency (best for alerts) or relevance. |
| Job type | jobType | select | any | hourly or fixed. |
| Experience level | experienceLevel | select | any | entry, intermediate, expert. |
| Client country | location | string | none | Full country name (United States, France). Two-letter codes return nothing. |
| Min/max hourly rate | hourlyRateMin / hourlyRateMax | integer | none | USD bounds for hourly jobs. |
| Min/max fixed budget | fixedBudgetMin / fixedBudgetMax | integer | none | USD bounds for fixed-price jobs. |
| Client hires | clientHires | select | any | No hires / 1–9 / 10+. |
| Contract-to-hire only | contractToHire | boolean | false | Only contract-to-hire postings. |
| Project duration | projectDuration | select | any | week, month, semester, ongoing. |
| Workload | workload | select | any | as_needed, part_time, full_time. |
| Client timezone | timezone | string | none | IANA name (America/New_York). |
| Skill / category ids | skillUid, categoryUid, subcategoryUid | string | none | Optional ids from a previous result or from a search URL. |
| Posted within | postedWithin | select | any time | Last 24 hours to 30 days. Applied on publishedAt. |
| Upwork search URLs | startUrls | array of URLs | none | Full search-result URLs, scraped with their own filters. |
| Maximum jobs | maxJobs | integer | 0 | Total cap (0 = every unique job this search returns). |
| Only new jobs since last run | incrementalMode | boolean | false | Skip job ids already returned for this search. |
| Fetch full descriptions | fullDescription | boolean | true | Include the full plain-text description. |
| Flatten output | flatten | boolean | false | Lists become comma-separated strings. |
| Report input status | emitInputStatus | boolean | true | Write an input_status report to OUTPUT. |
| Proxy configuration | proxyConfiguration | object | Apify Proxy, residential | Keep Apify Proxy on for cloud runs. |
Example input (alert feed):
{"query": "python","sort": "recency","jobType": "hourly","hourlyRateMin": 30,"postedWithin": "1","maxJobs": 50,"incrementalMode": true}
To reproduce an exact Upwork search, build it on the site and paste the results URL into startUrls.
📤 Output example
{"id": "2095999094643674588","ciphertext": "~022095999094643674588","url": "https://www.upwork.com/jobs/~022095999094643674588","title": "Python developer for data pipeline","description": "We need a Python developer to build and maintain ETL jobs…","jobType": "HOURLY","experienceLevel": "IntermediateLevel","hourlyRateMin": 30,"hourlyRateMax": 50,"fixedBudget": null,"durationWeeks": 12,"hourlyEngagementType": "PART_TIME","skills": ["Python", "ETL", "PostgreSQL"],"skillUids": ["1031626745410101248"],"publishedAt": "2026-09-05T00:16:16.967Z","searchInput": "python | hourly"}
The run's OUTPUT record also holds stats and, per search, an input_status entry with how many jobs Upwork announced, how many were collected, and why the search stopped.
💡 Ready-to-run examples
Hourly Python jobs, most recent first (alerts)
{ "query": "python", "sort": "recency", "jobType": "hourly", "maxJobs": 0, "incrementalMode": true }
Fixed-price design work in the United States
{ "query": "logo design", "jobType": "fixed", "location": "United States", "fixedBudgetMin": 100, "maxJobs": 100 }
From a pasted Upwork search URL
{ "startUrls": [{ "url": "https://www.upwork.com/nx/search/jobs/?q=react&sort=recency&t=0" }], "maxJobs": 0 }
Expert-level jobs posted today, flat CSV
{ "query": "machine learning", "experienceLevel": "expert", "postedWithin": "1", "sort": "recency", "maxJobs": 80, "flatten": true }
💰 Pricing: how much does it cost to scrape Upwork?
You pay only for the jobs you receive, with no subscription and no start fee. New Apify accounts get free monthly platform credits to try it. Cap volume with maxJobs, and narrow the set with filters before you pay for it.
⚙️ Performance, proxies and limits
- Speed: results come 50 jobs per page until the search is exhausted or you hit
maxJobs. - Completeness:
maxJobs: 0(the default) keeps going until every unique job for your filters is collected. Upwork serves about 5,050 jobs per raw search; when that is not enough the Actor continues with narrower slices (hourly vs fixed, client hires, experience, rate) and unions unique ids. Pages overlap slightly so a live feed that moved between requests does not drop listings. - Dedup: listings are unique on
ciphertext. Incremental mode remembers that id across runs of the same search. - Full descriptions come with each listing. Turn
fullDescriptionoff only if you want smaller records. - Proxy: keep Apify Proxy on for cloud runs; a residential proxy is the reliable default.
- Client panel (spend, verified payment, proposal count) is not part of the public job card this Actor returns.
🔌 Integrations and API
Run Upwork Jobs Scraper from the Apify API, the Python or JavaScript client, or on a schedule. Connect it to Make, Zapier, n8n, Google Sheets, Slack or any webhook through Apify integrations.
curl -X POST "https://api.apify.com/v2/acts/scrapifier~upwork-jobs-universal-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{ "query": "python", "sort": "recency", "maxJobs": 25 }'
❓ FAQ
Is it legal to scrape Upwork?
The Actor only reads job listings Upwork publishes to anyone without logging in. Descriptions can contain personal data, so process them in line with GDPR and other privacy laws, respect Upwork's terms of use, and stay responsible for how you use the data. This is not legal advice.
Do I need an Upwork account, login or cookies?
No. Nothing to log in to, and no cookies to paste.
How do I get only jobs posted since my last run?
Enable incrementalMode, keep sort on recency, and schedule the Actor. The dataset of each run then contains only new ciphertext values for that search.
How many jobs can one search return?
Set maxJobs to 0 (default) to collect every unique job for your filters, 50 per page. A single Upwork search stops around 5,050 results; the Actor then continues automatically with narrower slices and de-duplicates on ciphertext. Cap with maxJobs if you only want a sample.
Why is the client country empty when I did not set the location filter?
The public job card does not include the client's country. The location input filters the search to that country; it is not copied onto each row. Use searchInput to see which search produced the job.
Can I export to Excel or Google Sheets?
Yes. Every run's dataset downloads as CSV, XLSX, JSON or XML from the Storage tab. Turn on flatten for flat columns.
Does it get the full job description?
Yes. fullDescription is on by default.
🔗 Related scrapers
- Indeed Jobs Scraper: job listings on any Indeed country site, with salary and company profile.
- Glassdoor Jobs Scraper: job listings with Glassdoor company ratings and salary estimates.
💬 Support
Questions, bugs or a feature request? Open an issue in the Issues tab of this Actor. If Upwork Jobs Scraper saves you time, a rating on the Store helps others find it.