Upwork Jobs Scraper
Pricing
from $1.23 / 1,000 job saveds
Upwork Jobs Scraper
Export public Upwork jobs with descriptions, budgets, skills and visible client details. Filter and download matching freelance opportunities.
Pricing
from $1.23 / 1,000 job saveds
Rating
0.0
(0)
Developer
Hanna Nosova
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Share
Upwork Job Scraper
Use this Upwork job scraper to export public Upwork jobs with descriptions, budgets, skills, publication dates and visible client details to CSV, JSON or your own application.
- Find opportunities: search for freelance projects by keyword and source search operators.
- Evaluate public client facts: review country, payment verification, spending, hires and feedback where Upwork exposes them.
- Keep access limits visible: a public search preview can have account-restricted details. Such jobs have
detailStatus: "restricted", a warning, and no invented client object. - Stay within public data: this Actor does not sign in, accept account cookies, apply for jobs or collect private account information.
How to scrape Upwork jobs
Start with two jobs to check your search:
{"query":"web scraping","maxItems":2,"includeDetails":true}
For a broader feed, use {"query":"python","maxItems":50}. For a specific public client market, add "clientCountry":"Canada". Filters run against actual source fields and may require scanning more results than are saved.
Output example
This shortened example comes from an actual public job. Values change as Upwork updates the listing.
{"jobId": "2094154303070879807","url": "https://www.upwork.com/jobs/~022094154303070879807","title": "Build a Car Listing Scraper with Instant TG Notifications","jobType": "FIXED","fixedBudget": 10.0,"currency": "USD","client": {"country": "United Kingdom","totalSpent": 24305.91,"paymentVerified": true},"detailStatus": "complete"}
Full records include the description, skill identifiers, public client summary, activity and source metadata. Download results from the run's Dataset tab. The OUTPUT key-value record reports status, saved/scanned counts, source restrictions and any reason the run stopped early.
Who is it for?
- Freelancers: find projects matching their skills and budget.
- Agencies: monitor public demand and qualify opportunities using visible client information.
- Analysts: compare published skills, budgets and client markets over time.
- Developers: feed public job records into dashboards, spreadsheets and alert workflows.
Input settings
| Setting | JSON key | Meaning |
|---|---|---|
| Search query | query | Words or Upwork search operators. Defaults to web scraping when neither query nor searchUrl is supplied. |
| Public Upwork search URL | searchUrl | Optional https://www.upwork.com/nx/search/jobs/?q=... URL. Supports q and sort; use dedicated inputs for filters. Leave query blank when using this field. |
| Maximum saved jobs | maxItems | Stop after this many unique matching jobs. Public previews with restricted details count as jobs. |
| Jobs requested per page | pageSize | 1–50. Smaller pages can reduce unused search results in small runs. |
| Maximum search pages | maxPages | Bounds scanning when filters are narrow. Hitting this limit is reported as partial coverage. |
| Search order | sort | Newest publication first or Upwork relevance. |
| Published on or after | postedSince | ISO date or timezone-qualified timestamp; compared with the source publication time. |
| Job type | jobType | Keep fixed-price or hourly jobs. |
| Experience level | experienceLevel | Keep the requested source experience level. |
| Category name or slug | category | Match an exact public category or category-group name/slug, case-insensitively. Requires details. |
| Client country | clientCountry | Exact source country name, case-insensitive, such as Canada. This is the hiring client location, not the proxy or applicant location. |
| Explicitly remote jobs only | remoteOnly | Require the source to explicitly label REMOTE. Unspecified arrangements are excluded; Upwork often leaves this field unspecified. Requires details. |
| Verified-payment clients only | paymentVerifiedOnly | Require a public true payment-verification value. Missing/restricted values do not match. |
| Include public job and client details | includeDetails | Default true. Retrieve full public description, category, client facts and activity. Account-restricted jobs retain their public preview with detailStatus=restricted. |
| Fail on incomplete extraction | failOnBlocked | Fail on source blocks, unexpected errors or scan limits, while preserving saved jobs. False permits an explicitly partial run. Zero-row blocks always fail. |
| Request timeout in seconds | requestTimeoutSecs | Maximum time for one public request, capped by the shared runtime deadline. |
| Total runtime budget | maxRunSeconds | Includes a shutdown reserve of at least 30 seconds and 10 percent. Increase for many jobs or restrictive filters. |
| Maximum session attempts per operation | maxSessionAttempts | Bounded retry count for guest bootstrap, network failures and HTTP blocks. Account restrictions are not retried. |
| Apify proxy configuration | proxyConfiguration | Automatic US datacenter selection is tried first, with residential fallback after a session failure. Explicit proxy groups are respected. No external proxy credentials are accepted. |
| Minimum hourly rate | hourlyRateMin | Local filter on the corresponding public source value; unavailable values do not match. |
| Maximum hourly rate | hourlyRateMax | Local filter on the corresponding public source value; unavailable values do not match. |
| Minimum fixed budget | fixedBudgetMin | Local filter on the corresponding public source value; unavailable values do not match. |
| Maximum fixed budget | fixedBudgetMax | Local filter on the corresponding public source value; unavailable values do not match. |
| Minimum public client spend | minClientSpend | Local filter on the corresponding public source value; unavailable values do not match. |
| Minimum client rating | minClientRating | Local filter on the corresponding public source value; unavailable values do not match. |
| Maximum proposal count | maxProposals | Local filter on the corresponding public source value; unavailable values do not match. |
| Description/title must include all | includeKeywords | Case-insensitive text filters applied to the full public detail when available, otherwise to the public preview. |
| Description/title must exclude all | excludeKeywords | Case-insensitive text filters applied to the full public detail when available, otherwise to the public preview. |
searchUrl accepts public job-search URLs containing q and sort. Other URL filters produce a clear validation error; use the dedicated Actor inputs instead. If both URL and query are supplied, they must agree.
remoteOnly requires an explicit source REMOTE value. Many jobs leave their work arrangement unspecified; these do not match that strict filter. A client's country is different from applicant-location restrictions. Company size is the source's classification, not an inferred employee count.
Output fields
| Field | Meaning |
|---|---|
jobId | Stable source job ID |
ciphertext | Source public job ciphertext |
url | Canonical Upwork job URL |
title | Source title |
description | Full public description when details are complete; source search preview otherwise |
jobType | FIXED or HOURLY |
query | Requested search expression |
sourceUrl | Public search URL |
scrapedAt | UTC collection timestamp |
detailStatus | complete, restricted or not_requested |
currency | Source budget currency; never inferred from viewer |
experienceLevel | Normalized source experience level |
workload | Source workload |
createdAt | Source creation timestamp |
postedAt | Source publication timestamp |
status | Source job status |
detailSource | Public detail source |
workArrangement | remote, on_site or unspecified, from onSiteType |
fixedBudget | Source fixedBudget; null when not applicable or unavailable |
hourlyRateMin | Source hourlyRateMin; null when not applicable or unavailable |
hourlyRateMax | Source hourlyRateMax; null when not applicable or unavailable |
weeklyRetainerBudget | Source weeklyRetainerBudget; null when not applicable or unavailable |
premium | Source premium flag |
skills | Source skill identifiers and labels |
warnings | warnings |
duration | duration |
category | category |
categoryGroup | categoryGroup |
client | Public client summary; omitted for restricted previews |
activity | activity |
qualifications | Public applicant/location requirements, distinct from client country |
The client object includes country, city, timezone, totalSpent, totalHires, activeHires, hoursBilled, reviewCount, rating, jobsWithHires, openJobs, memberSince, paymentVerified, companyIndustry and companySize. Individual values can be null when Upwork does not disclose them; zero is kept as zero.
activity includes totalApplicants, totalHired, totalInvitedToInterview, unansweredInvites, invitationsSent, numberOfPositionsToHire and lastBuyerActivity. qualifications preserves public countries, regions, states, timezones, localMarket, onSiteType, prefEnglishSkill, risingTalent and locationCheckRequired. Empty location requirements must not be interpreted as the client's location.
Pricing
The start event is charged once when the first matching job is ready to save. The item event is charged for each unique saved job. A useful public preview with restricted details counts as a saved job and is clearly marked. Error/status messages are written to the run summary and are not dataset jobs.
See the current pricing and discounts. No additional Upwork account or external data subscription is required.
Tips and limits
- Keep
includeDetailsenabled for public client fields and complete descriptions. Turning it off intentionally exports only search previews. - A genuine empty search can succeed with zero rows. A challenge, malformed response or failed bootstrap cannot.
- Results reflect a changing marketplace. Closed, removed, private or restricted jobs may become unavailable between search and detail retrieval.
- Tight filters can scan many jobs.
maxPagesand the runtime budget bound this work; inspect the run summary for partial coverage. - With
failOnBlocked=true, unexpected blocks or incomplete extraction fail the run while preserving jobs already saved. - Source IDs control duplicates. Reuse job IDs in your own database when combining separate runs.
- Residential proxy access is required for the verified route. The default configuration selects Apify residential US proxies.
- Upwork's source fields can omit spend, location, rating or rates. This Actor does not fill them with guesses.
- This Actor is independent of Upwork and does not automate applications or contact job posters.
Upwork jobs API integration
Use your own Apify token as an environment variable. A run returns a default dataset ID.
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('fetch_cat/upwork-jobs-scraper').call({query: 'python', maxItems: 20, includeDetails: true});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("fetch_cat/upwork-jobs-scraper").call(run_input={"query": "python", "maxItems": 20, "includeDetails": True})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
cURL
$curl --request POST --header "Authorization: Bearer $APIFY_TOKEN" --header "Content-Type: application/json" --data '{"query":"python","maxItems":20,"includeDetails":true}' "https://api.apify.com/v2/acts/fetch_cat~upwork-jobs-scraper/run-sync-get-dataset-items"
For longer searches, start an asynchronous run and read its dataset after completion.
MCP and AI agents
Connect through the Apify MCP server. One local configuration is:
{"mcpServers": {"apify": {"command": "npx","args": ["-y", "@apify/actors-mcp-server", "--actors", "fetch_cat/upwork-jobs-scraper"],"env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }}}}
CLI: npx -y @apify/actors-mcp-server --actors fetch_cat/upwork-jobs-scraper.
Example prompt: “Find 20 public Python freelance jobs. Keep public client details, identify restricted previews, and compare budgets without inventing missing rates.”
FAQ
What data can I export with upwork job scraper? Export titles, job IDs, URLs, descriptions, skills, publication dates and available budgets. Full public details also include visible client facts and activity; restricted details are flagged explicitly.
Can I run Upwork Jobs Scraper through an API, schedule, or MCP client? Yes. Use the API examples or Apify MCP configuration above. Save an input as a task to schedule it, and deduplicate scheduled results using jobId.
How much does it cost to use Upwork Jobs Scraper? A one-time search event applies when the first matching job is ready, plus one event per saved job. The Pricing tab shows the current rate for your plan. Account-restricted public previews count as saved jobs.
Does this need an Upwork login? No. It uses public job data and will not ask for your Upwork cookies.
Why does a job have no client object? Upwork may expose the search preview while requiring registration for details. Check detailStatus and warnings.
Are null spend and zero spend equivalent? No. Null means the source did not disclose the value. Zero is a source value.
Why did a restrictive filter return fewer jobs? Only observed matching values qualify. Missing or restricted values do not count as matches, and the scan has page/time limits.
Can I schedule it? Use an Apify task and schedule after confirming the input. Use job IDs to avoid duplicates across scheduled runs.
Related Actors
Explore Indeed Jobs Scraper and LinkedIn Jobs Scraper for other job markets. Also compare Glassdoor Jobs Scraper, Google Jobs Scraper and RemoteOK Jobs Scraper. Their source coverage differs from Upwork.
Support
Report bugs or wrong output through this Actor's Issues tab. Include the Apify run ID or run URL, input JSON, expected and actual output, and one reproducible public Upwork URL. Never share cookies, tokens or private account information.