Upwork Jobs Scraper: Multipage Job Search & Client Data
DeprecatedPricing
from $1.60 / 1,000 jobs
Upwork Jobs Scraper: Multipage Job Search & Client Data
DeprecatedScrape Upwork freelance jobs across multiple search pages. Collect descriptions, skills, budgets and client details. Filter and export JSON, CSV or Excel.
Pricing
from $1.60 / 1,000 jobs
Rating
0.0
(0)
Developer
Stan Van Rooy
Maintained by CommunityActor stats
7
Bookmarked
73
Total users
1
Monthly active users
13 days ago
Last modified
Categories
Share
Upwork Jobs Scraper: Job Search, Budgets & Client Data
Search Upwork freelance jobs across multiple result pages and export structured data to JSON, CSV or Excel. Collect job titles, full descriptions, skills, hourly rates, fixed-price budgets, experience levels and posting dates. Add public client information and proposal activity when you need richer qualification data.
Use keywords such as python developer, Shopify, AI automation or virtual assistant. The Actor follows Upwork's public guest-search pagination, removes duplicate job IDs and keeps collecting until it reaches your result limit, the available results or your page budget. No Upwork login, cookies or personal API key is required.
Quick start: search beyond the first page
{"search": "python developer","limit": 150,"include_details": false,"sort": "newest"}
On a paid Apify plan, this requests up to 150 unique jobs across successive search pages. Free-plan accounts stop at 100 rows per run. Actual output depends on the query, filters and Upwork availability.
Fast listing mode: include_details: false reads full descriptions, skills and budgets directly from search results. It avoids a separate page request for each job. At a page size of 50, 150 unfiltered results require three search-page requests plus guest-session setup.
Enriched mode: include_details: true (the default) also visits each selected job's public page to collect available client and application information. These extra requests take longer.
Search several topics in one run
{"searches": ["python automation", "Shopify developer", "AI integration"],"limit": 300,"include_details": false}
Queries run in input order and share one output limit. Duplicate jobs are saved once. An earlier query can fill the limit before later queries are reached. newest applies within each query; the combined dataset is not globally sorted across queries.
Filter freelance opportunities
{"search": "python","keywords": "automation","job_type": "hourly","min_hourly_rate": 25,"contractor_tier": ["2", "3"],"limit": 50,"include_details": true}
Keyword search, contract type, experience level and category are sent to Upwork's guest search. Additional keywords and budget checks are applied to the returned jobs. The Actor continues through later pages when local filters remove results.
Upwork may broaden an unquoted search to related results, even for an unfamiliar term. To request an exact phrase, include quotes inside the search value, for example "search": "\"python developer\"". Use keywords when every supplied word must appear in the returned title, description or skills.
What you get
| Data | Fast listing mode | With job details |
|---|---|---|
| Complete job ID, URL, title and description | Yes | Yes |
| Skills, experience level and contract type | Yes | Yes |
| Fixed budget or hourly range, when published | Yes | Yes |
| Posting date, publish date and project duration | Yes | Yes |
| Client country, city, verification and rating | — | When public |
| Client spending, hours and hiring history | — | When public |
| Proposal range, applicants, interviews and invitations | — | When public |
| Category and category group in the output | — | When public |
Missing fields remain absent or null. Decimal budgets, client spending and billed hours retain their precision. detail_status distinguishes not_requested, complete and failed enrichment.
Input reference
Provide at least one of search, searches or start_urls.
| Parameter | Default | Description |
|---|---|---|
search | — | Upwork job-search keywords. |
searches | [] | Up to 20 additional keyword queries, combined with search. |
limit | 10 | Maximum unique output jobs across all inputs, from 1 to 1,000. |
include_details | true | Add public client and job activity details. Disable for faster listing-only collection. |
sort | newest | newest or relevance, applied by Upwork within each query. |
job_type | both | both, hourly or fixed. |
contractor_tier | [] | Experience levels: "1" entry level, "2" intermediate, "3" expert. |
category | — | Optional category or subcategory selected in the input form. |
keywords | "" | Additional local filter across title, description and skills. All supplied words must match. |
min_fixed_price, max_fixed_price | — | USD budget range, applied to fixed-price jobs. |
min_hourly_rate, max_hourly_rate | — | USD hourly range. A job qualifies when its published range overlaps yours. |
page_size | 50 | Jobs requested per search page: 10, 20 or 50. |
max_pages | 100 | Maximum search pages per query, from 1 to 200. Bounds work when filters are restrictive. |
max_concurrency | 4 | Concurrent detail requests, from 1 to 8. Search pages are fetched sequentially so limits and pagination can be checked. |
start_urls | [] | Up to 100 supplemental public Upwork skill or job URLs, processed after search queries if output capacity remains. |
A limit is a ceiling, not a promised result count. Budget filters exclude jobs whose required budget is unknown. Set job_type explicitly if you want only one contract type. Restrictive filters may require more pages; RUN_SUMMARY indicates when max_pages stopped the run.
Direct job and skill URLs
Use public /jobs/~ID/ or /freelance-jobs/apply/TITLE_~ID/ links to revisit known jobs. Direct job URLs always load the job details.
{"start_urls": ["https://www.upwork.com/freelance-jobs/shopify/"],"limit": 20,"include_details": false}
Skill URLs are a different source: /freelance-jobs/<skill>/ pages expose a limited public sample, currently up to 30 jobs. They do not paginate. Use search: "shopify" for paginated retrieval. Category filtering of explicit URLs requires detail requests, even in listing mode.
Output example
Illustrative listing-mode row:
{"id": "022000000000000000001","url": "https://www.upwork.com/jobs/~022000000000000000001/","title": "Python developer for workflow automation","description": "Build a Python workflow that connects our reporting tools.","job_type": "hourly","skills": ["Python", "API Integration"],"experience_level": "Intermediate","contractor_tier": "2","fixed_budget": null,"hourly_min": 25.5,"hourly_max": 50,"duration": "1 to 3 months","posted_at": "2026-10-01T08:00:00Z","scraped_at": "2026-10-01T09:00:00+00:00","search_query": "python developer","search_offset": 50,"detail_status": "not_requested"}
Enrichment adds flat fields such as client_location_country, client_payment_verified, client_stats_total_spent, client_stats_total_hours_hired, job_activity_proposals_min and job_activity_interviewing.
Export, monitor and integrate
Download results as JSON, CSV or Excel from the run's Output tab. Use the Apify API or schedules for recurring opportunity tracking, agency research, budget analysis and freelance-market reporting. To identify newly discovered jobs across runs, compare the complete id field; deduplication within a run does not create a persistent history.
The Run summary output links to RUN_SUMMARY, which records page offsets, unique IDs discovered per page, total jobs reported by Upwork, saved rows, request counts and errors. This makes it possible to verify that the Actor progressed beyond page one.
Reliability and limitations
- Search uses the jobs available to anonymous Upwork visitors. Private or account-restricted listings are not included.
- Search results change while a run is in progress. Deduplication prevents repeated output, but a live search is not a historical snapshot or a guarantee of complete coverage.
- A repeated page with no new IDs, an unexpected offset, a rejected request or an invalid response is treated as a failure—not a successful empty search.
- A valid search with no matches completes with zero rows and an explicit result message.
- If enrichment or a later search page fails, already-saved rows remain available and the run is marked failed. Check
detail_statusandRUN_SUMMARYbefore retrying. - Reaching the result limit or
max_pagesends the run gracefully with an explicit status message. - Upwork can change its guest interfaces, restrict access or remove jobs. No fixed success rate is promised.
Pricing and Free-plan sample
Apify Free accounts can collect up to 100 result rows total per run, shared across all queries and URLs. The Actor stops requesting further pages once that output cap is reached and applies it before detail enrichment. Upgrade your Apify plan for larger runs. Normal Actor charges apply, including any applicable start charge on runs with no results. See the Store pricing panel for current charges.
The sample resets each run; it is not a daily or monthly quota. Paid accounts can request up to 1,000 unique jobs per run, subject to source availability and the configured page budget.
October 2026 update
This release replaces the former HTML search path, which began returning a login page, with paginated guest search. It adds multiple queries, optional faster listing mode, direct URLs, full-ID deduplication, structured job and client data, and explicit failure reporting. Existing budget, experience and category inputs remain available.
For support, open the Actor's Issues tab with the run URL and a non-sensitive input example.