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
Fetch Cat
Maintained by CommunityActor stats
0
Bookmarked
14
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Features
Share
Export public Upwork job previews and available public details, including descriptions, skills, publication dates, budgets and visible client facts. Account-restricted details stay marked as restricted, with no invented client object. The Actor does not sign in, accept account cookies, apply for jobs or collect private account information.
Quick start
Start with the existing two-job web-scraping search, then inspect source links and detailStatus before expanding the cap:
{"query":"web scraping","maxItems":2,"includeDetails":true}
The existing broader feed uses python with a fifty-job cap. A client-country filter such as Canada matches the hiring client's exposed country rather than the applicant's location. Narrow filters can scan more candidates than they save.
Prefer a video guide? This short Apify walkthrough shows you how to set up and run an Actor. It uses a different Actor, but the setup steps are the same.
Ready-to-run examples
Open a public example to inspect its input, run it, or reuse it as a task:
What you get
One unique matching job row with its source ID, URL, title, available description, skills and budget values. Public client facts and activity accompany complete details, while restricted previews remain useful labeled records. OUTPUT reports saved and scanned counts, restrictions and early-stop reasons.
Who is it for?
- Freelancers shortlisting public opportunities against their own skills and budget requirements.
- Agency research teams inspecting exposed demand and client context without automating outreach.
- Labor-market analysts comparing bounded skill and budget samples with their publication times.
- Data developers maintaining source-ID-based job datasets and downstream reports.
How you can use the data
- Triage a web-scraping opportunity sample. Collect a small query sample and inspect title, description, skills and source URL. Keep detailStatus beside each record so a restricted preview is not presented as a complete brief.
- Compare observed Python budgets. Use the existing python query and keep fixed-price and hourly values in separate columns with their source currency. Missing rates stay null rather than becoming zero or an estimated market price.
- Review a client-market subset. Apply the existing Canada client-country example and inspect the exposed client facts. Client location differs from public applicant-country requirements, and a missing or restricted verification, spend or rating value does not satisfy a strict filter.
- Join recurring exports in your own store. Keep jobId, publication time and collection time to avoid duplicate records across scheduled runs. Use Apify schedules and your own comparison or alert logic, allowing closed or restricted listings to change between observations.
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: if Upwork refuses job details, found jobs are saved as search previews with detailStatus=unavailable (not with client-detail filters). 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 selection tries up to two Apify datacenter sessions, then residential if needed within the session-attempt limit (US by default). 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 data
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.
| 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, unavailable (Upwork refused details; search preview saved) 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.
Download your results
Open your run's dataset, choose Export and select JSON, CSV or Excel. JSON keeps nested fields together. CSV and Excel are useful when you want to review the records in a spreadsheet.
See Apify's download and export guide for the available formats and field options.
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 for best results
- Keep public details on when needed. Turning them off intentionally exports search previews instead of full descriptions and client facts.
- Begin with a small query and cap. Tight filters can scan many candidates before finding qualified rows.
- Review detailStatus and warnings. Restricted previews are saved jobs, while source restrictions must remain visible.
- Use IDs for repeat exports. Keep jobId and source timestamps in your own destination before producing comparisons.
- Separate missing facts from measured zero. Source-null spend, ratings and rates must not be replaced with guesses.
Limits and caveats
- 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. WithfailOnBlocked=false, jobs whose details Upwork refuses are saved as labeled search previews (detailStatus=unavailable) and OUTPUT reportsunavailableDetails. - The maximum supported memory allocation is 1024 MiB. Existing lower-memory task settings are unchanged, but browser recovery headroom at 256 MiB has not been verified.
- Public HTTP and browser-search JSON responses are limited to 8 MiB after decompression. Search pages may contain at most 50 jobs. Oversized responses stop extraction without retries, retain saved jobs and report
RESPONSE_TOO_LARGE, not an empty-search success. - Source IDs control duplicates. Reuse job IDs in your own database when combining separate runs.
- Apify proxies are required. Automatic selection starts with a datacenter session and can fall back to residential traffic. Explicit proxy groups are respected. Narrow filters may scan more jobs than they save.
- If a run reaches its maximum total charge or time limit, it stops starting new work, keeps the jobs already saved and finishes successfully with a status message that says why. A time limit under about two minutes may not leave enough time to search.
- 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.
Automation and integrations
Save your settings for next time
Once you have an input that works for you, save it as an Apify task. This keeps your settings together so you can use them again without filling in the form from scratch.
Run on a schedule
Need fresh results regularly? You can schedule the Actor or a saved task to run at a time that suits you.
Each scheduled run collects the data again. If you want to compare results or highlight changes, add that step in your own workflow.
Send results to your other tools
Use n8n, Make or Zapier to connect this scraper to the rest of your workflow. For example, you could pass its results to an AI assistant or add records to a spreadsheet. Follow the Apify integration guides for your chosen tool.
For a custom connection, an Apify webhook can notify your app when a run finishes or fails. Your app can then fetch the results or handle the failure.
API usage
Want to collect this data from your own app or automation? The examples below send input to the scraper and show how to collect its results.
The existing Node.js and Python examples wait for completion and read dataset results. This cURL example uses the synchronous result endpoint and returns dataset items. For longer searches, start an asynchronous run, wait for completion and read its dataset with pagination.
For setup instructions, see Apify's JavaScript client guide, Python client guide and Actor runs API reference.
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"
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)
MCP and AI agents
You can ask your AI assistant to collect data with Upwork Jobs Scraper and help you work with the results. The scraper returns the data, and your assistant can then summarize it, compare records or prepare notes.
Connect your assistant through the Apify MCP server. MCP gives your assistant a way to find this scraper, run it and read the results. Follow the official setup and sign-in guide for your app.
Easier setup with an Apify plugin
If you use a supported coding assistant, the official Apify plugin can set up the connection for you. It connects your assistant to Apify and includes instructions for common tasks. Follow the guide for your particular app.
Use Apify AI in Console
Prefer to keep everything in Apify? Open Apify AI in Console and ask it to find Fetch Cat's Upwork Jobs Scraper. You can describe the data you want and ask questions about the results.
Apify AI is currently in beta. It asks for confirmation before starting an Actor, and normal run charges apply.
Choose your assistant
- Claude and Claude Code (Anthropic): Apify setup guide.
- ChatGPT and Codex (OpenAI): Apify setup guides.
- Grok Bot (xAI): Apify plugin guide.
- Gemini CLI (Google): MCP server setup guide. Use the server URL below with the HTTP configuration supported by Gemini CLI.
Connect just this scraper
To keep your setup focused on this scraper, add this server configuration to a compatible MCP client:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=fetch_cat/upwork-jobs-scraper"}}}
Sign in to Apify when your client asks. If your client uses a Bearer token instead, follow its setup guide and keep the token in its secure configuration. Configuration formats vary by app, so use the linked guide if your client needs a different format.
Use Apify's general server
Already connected to the general Apify MCP server at https://mcp.apify.com? You can use it to find this scraper without adding another server. Ask your assistant to use Upwork Jobs Scraper by Fetch Cat, or give it the identifier fetch_cat/upwork-jobs-scraper.
Your assistant can check the available settings and retrieve the results from the returned run. If the run is still working, it should follow that run rather than start it again. Both connection options use Apify's hosted service.
Example requests
- “Use Fetch Cat’s Upwork Jobs Scraper to collect up to 2 public web scraping jobs with public details enabled. Keep titles, links, available budgets and restricted-detail labels without applying or inventing client information.”
- “Collect up to 5 public Python jobs from clients whose exposed country is Canada, with details enabled. Separate fixed and hourly budgets and preserve missing values without confusing client country with applicant restrictions.”
- “Retrieve up to 5 public web scraping jobs with details off. Keep IDs, publication times and preview text, and explain which detail fields are unavailable rather than logging in or treating previews as complete briefs.”
Normal Apify charges apply. Check the live Pricing tab before asking your assistant to run a larger batch.
Pay with x402
If your AI agent has a funded wallet, it can pay for Apify usage through x402. This experimental option lets an agent use Apify without a conventional account.
Apify AGI provides a prepaid API token with a spending cap after payment. Your agent can use that token to run this scraper through the Apify API or an authenticated MCP connection.
Some MCP setups also support paying for each request directly. That is a different payment option, so check the official guide for its availability.
Follow the official guide for wallet setup, supported payment options and current terms. Apify handles the payments. Keep wallet keys and payment tokens in your agent's secure configuration.
Other ways for agents to pay
Apify also supports MPP for prepaid access through AGI and Skyfire for eligible Actors. If your agent already uses one of these, see the agentic payment guide to choose the right setup.
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
- Indeed Jobs Scraper — Collect public Indeed job listings and available job details.
- LinkedIn Jobs Scraper — Collect public LinkedIn job listings and available job details.
- Glassdoor Jobs Scraper — Collect public Glassdoor job listings and available employer context.
- Google Jobs Scraper — Collect job listings exposed in public Google Jobs results.
- RemoteOK Jobs Scraper — Collect public RemoteOK remote job listings and available job details.
Support and feedback
For custom additions or integrations, email hello@fetchcat.dev.
Found an error or have a feature request? Open an issue with the run URL, a non-sensitive input example and what you expected.
Need help sharing it? See Apify’s guide to sharing a run when reporting an issue. Sharing a run can give the developer access to its input, logs and results, so use a run that contains no sensitive data. Please leave out API tokens, passwords, cookies, private documents and personal data. Use a public sample URL or a redacted example instead.
Tried this scraper? We'd love to hear how it worked for you. Leave a review to help others choose the right tool and help us improve it. Your feedback means a lot to us.
Made with care for curious people, AI agents and the possibilities in data. ♥