Upwork Job Scraper (Pay Per Result)
Pricing
from $6.50 / 1,000 jobs
Upwork Job Scraper (Pay Per Result)
Scrape recent and relevant Upwork.com jobs, filter and only pay for what you need. Unauthed runs = no ban risk.
Pricing
from $6.50 / 1,000 jobs
Rating
0.0
(0)
Developer
Matthew James
Maintained by CommunityActor stats
4
Bookmarked
78
Total users
5
Monthly active users
a day ago
Last modified
Categories
Share
🔎 Upwork Job Scraper
Find Upwork jobs by keyword or search URL. Filter the results, download them, or send them to your workflow.
No Upwork login needed for basic results. Add your Upwork authorization header or cookies for available client information and Extra Details.
📦 What you get
🧾 Example output
Without authentication — 16 standard fields
Client information and proposal counts are null. There is no Extra Details field.
{"Job ID": "1000000000000000001","Time Posted": "2026-09-04T14:18:13.670Z","Project Payment Type": "Hourly","Budget": "$8.0 - $12.0","Skill Level": "Intermediate","Title": "Example automation job","URL": "https://www.upwork.com/jobs/~example1","Description": "Build a Node.js integration with clear tests.","Location": null,"Total Spent": null,"Feedback": null,"Proposals": null,"Project Length": "1 to 3 months","Weekly Hours": "Less than 30 hrs/week","Skills": ["Node.js", "API Integration"],"Date Scraped": "2026-09-12T12:00:00.000Z"}
With authentication — client information and Extra Details
The same 16 fields stay in place. Available client values are filled in, and Extra Details is added automatically unless turned off. Some values may still be null.
{"Job ID": "1000000000000000003","Time Posted": "2026-08-21T17:52:00.733Z","Project Payment Type": "Hourly","Budget": "$30.0 - $123.0","Skill Level": "Intermediate","Title": "Example automation job","URL": "https://www.upwork.com/jobs/~example3","Description": "Build a Node.js integration with clear tests.","Location": "United States","Total Spent": "$18,854.87","Feedback": 4.97,"Proposals": 8,"Project Length": "Less than 1 month","Weekly Hours": "Less than 30 hrs/week","Skills": ["Node.js", "API Integration"],"Date Scraped": "2026-09-12T12:00:00.000Z","Extra Details": {"Job": {"Status": "Active","Start Date": null,"Category": "Scripts & Utilities","Category Group": "Web, Mobile & Software Dev","Occupation": "Scripting & Automation","Additional Skills": [],"Tools": ["Zapier"],"Screening Questions": ["Describe a similar integration you have built."],"Attachments": []},"Client": {"City": "Austin","Timezone": "America/Chicago","Payment Verified": true,"Enterprise": false,"Company": null,"Review Count": 12,"Assignments": 15,"Active Assignments": 2,"Hours Billed": 250,"Jobs Posted": 18,"Open Jobs": 2,"Jobs With Hires": 10,"Average Hourly Rate": null,"Work History": []},"Requirements": {"Freelancer Type": "Independent","English Level": "Fluent","Languages": ["English"],"Min Job Success Score": 90,"Min Upwork Hours": 100,"Portfolio Requested": false,"Rising Talent Preferred": false,"Countries": null,"Regions": null,"States": null,"Timezones": null,"Location Check Required": false,"Location": null,"On Site": null},"Activity": {"Last Client Activity At": "2026-09-12T11:30:00.000Z","Hires": 0,"Interview Invites": 2,"Unanswered Invites": 1,"Invites Sent": 3,"Positions To Hire": 1},"Bid Stats": {"Average": {"Amount": 50,"Currency": "USD"},"Lowest": {"Amount": 30,"Currency": "USD"},"Highest": {"Amount": 100,"Currency": "USD"}}}}
Each job is one row with these 16 standard fields:
| Group | Output fields |
|---|---|
| Job | Job ID, Title, URL, Description, Skills |
| Pay and experience | Project Payment Type, Budget, Skill Level |
| Schedule | Project Length, Weekly Hours, Time Posted, Date Scraped |
| Client and activity | Location, Total Spent, Feedback, Proposals |
Location means the client's country, not where applicants must live. Without authentication, client and proposal values are unavailable. The standard fields remain present.
With valid authentication, Extra Details is added to the same row:
| Group | Examples of available details |
|---|---|
| Job | Category, screening questions, attachment links |
| Client | Payment status, work history, jobs posted |
| Requirements | Languages, location rules, experience requirements |
| Activity | Hires, invitations, recent client activity |
| Bid Stats | Average, lowest, and highest bids |
Details vary by job. null means unavailable; [] means an empty list. Matching details already shown in standard fields are not repeated.
To turn off Extra Details, add "enrichDetails": false in the JSON input editor. Remove that setting to enable automatic details with authentication.
Download JSON, CSV, or Excel. Use JSON to keep the full Extra Details structure.
🎯 Choose your filters
| Filter | What it does |
|---|---|
| Job type, budget, experience, and workload | Narrow the jobs you want. |
| Sort Order | Ask Upwork for most recent or most relevant results. The Actor does not sort results afterward. |
| Maximum Job Age (hours) | Use 24 for one day or 0.5 for 30 minutes. 0 turns this filter off. |
| Include / Exclude Keywords | Keep or skip jobs based on their text. |
| Client Countries | Select countries to include or exclude. If both lists contain a country, exclusion wins. |
| Client payment, spending, rating, and reviews | Keep jobs from clients that meet your limits. Authentication is needed for these fields. |
| Maximum Proposals | Keep jobs at or below this count. 0 means no proposals; leave empty for no limit. |
Missing data does not pass a filter. Selecting Canada excludes jobs with no client country. Maximum Proposals excludes jobs without an exact count.
The country list contains locations seen in Upwork results, so it may not include every country. The job-age cutoff stays fixed from run start through retries and restarts. Jobs without a posting time cannot pass that filter.
📝 Input guidance
- Use Residential proxies for better reliability. They are selected by default.
- For client information and Extra Details, add a current Upwork authorization header or cookies. The authorization header is recommended.
- A Custom Search URL overrides Search Query and the matching search controls. Freshness, keyword, and client filters still apply to the results.
- If you use cookies, export the full set from a signed-in Upwork browser session as a JSON array. Keep both cookies and authorization headers secret.
- If both are supplied, the authorization header takes priority. A token rejected during search stops the run; the Actor does not switch to cookies.
- Without a header, incomplete or rejected cookies can fall back to basic results with a warning. Malformed inputs must be fixed before the run can start.
- Without valid authentication, you may get fewer jobs and pages. Filters that need client data or exact proposal counts exclude jobs when those values are missing.
- Unavailable values are
null. Valid authentication does not guarantee that every field is available.
🔐 Add your Upwork login details
🔑 Authorization Header (recommended)
- Sign in to Upwork and open your browser's developer tools.
- Select Network, then reload the page or open a job.
- Open an Upwork request and find
authorizationunder Request Headers. - Copy its value into Authorization Header (recommended). The
Bearerprefix is optional.
Use your Upwork token, not an Apify API token or a cookie value.
🍪 Cookies (alternative)
Export the full cookies from your signed-in Upwork session as a JSON array. Paste the array into Cookies (alternative).
Both inputs are encrypted. Keep them private and replace them when they expire. Renewal is not automatic.
If you supply both, the authorization header takes priority. Rejected cookies can fall back to basic results. A token rejected during search stops the run.
⏱️ Results and run limits
- Pages to Scrape: Up to 100 pages, with 50 jobs requested per page. Fewer than 50 returned jobs ends the search. This count is checked before filters.
- Maximum Matching Results: Limits jobs saved after filtering and removing duplicates. Strict filters may scan many pages without saving any jobs.
- Run time: New requests stop after one hour, including retries and restarts. Current requests and saves may finish afterward.
- Spending limits: Apify's remaining result allowance also limits saved jobs and optional details.
Page size is fixed. Old page-size inputs and page-size values in custom URLs are ignored. Restarting a run does not reset its detail-request limit.
For the pay-per-result version, each saved job counts as one result. Extra Details adds no separate result. Filtering jobs later in your workflow does not reduce the number of delivered results.
🔗 Automate your workflow
Use Apify schedules for regular searches. Set a job-age limit to focus on fresh jobs. Keep your Upwork credentials current.
- Connect Apify using your Apify API token, not your Upwork token.
- Run this Actor and wait for success.
- Use Get Dataset Items with the dataset ID from that run.
- Filter Extra Details if needed, then save jobs or send alerts.
For example, to keep jobs with no hires, require Extra Details → Activity → Hires to equal 0. A missing value is not zero.
Already using a schedule? Add a Run succeeded webhook in the Actor's Integrations tab. The webhook sends run information, not jobs. Fetch results using resource.defaultDatasetId; do not start another scrape. See the webhook guide.
Save handled Job ID values to avoid duplicate alerts across runs. Ignore repeated webhook run IDs, skip empty datasets, and handle failed runs separately.
💡 Troubleshooting
| Problem | What to check |
|---|---|
| No results | Check the run status. For a successful run, try fewer filters. A failed run does not prove there were no matches. |
| Missing client data | Replace expired Upwork credentials. Some values may be missing even with valid access. Basic access can return fewer jobs and pages. |
| Missing Extra Details | Check credentials and the enrichDetails setting. If details fail or reach their limit, selected jobs are still saved with unavailable details. |
| Run stopped early | Check its status and saved results. Failed runs can contain useful partial results. |
| Duplicate jobs across runs | Each job appears once per run, but can appear again in a later run. Match by Job ID when combining results. |
| No alert after a successful run | Check your workflow and webhook delivery. A successful scrape does not guarantee an alert was sent. |