Upwork Job Scraper
Pricing
from $3.00 / 1,000 jobs
Upwork Job Scraper
Scrape recent and relevant Upwork.com jobs, filter and only pay for what you need. Unauthed runs = no ban risk.
Pricing
from $3.00 / 1,000 jobs
Rating
4.9
(8)
Developer
Matthew James
Maintained by CommunityActor stats
28
Bookmarked
548
Total users
13
Monthly active users
8 days ago
Last modified
Categories
Share
π Upwork Job Scraper
Find Upwork jobs by keyword or search URL. Download results or send them to your workflow. Upwork applies native search filters; use your own workflow for additional filtering.
No Upwork login needed for basic results. Add your Upwork authorization header or cookies for available client information. Turn on Add Extra Details if you also want job requirements, client history, and hiring activity.
π¦ 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 and Add Extra Details
Authentication fills in available client values in the same 16 standard fields. The example below also has Add Extra Details turned on. Without that add-on, the Extra Details key is omitted. 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 and Add Extra Details enabled, 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.
Extra Details is off by default. Turn on Add Extra Details in the Input form, or set "paidEnrichment": true in JSON. Adding authentication alone does not enable the add-on. Native search filters work without the add-on.
Check Pricing for the enrichment fee. While no add-on fee is configured, Extra Details is included without an extra charge. Once that fee is active for your run, each saved job with usable Extra Details has the listed fee. Standard result and other listed charges still apply.
For older saved tasks, enrichDetails no longer turns on details or authorizes an extra charge. Use the new paid option to opt in. Start a new run when changing these settings.
Download JSON, CSV, or Excel. Use JSON to keep the full Extra Details structure.
π― Choose your search
| Control | What it does | Authentication |
|---|---|---|
| Search Query | Use keywords, phrases, or AND, OR, and NOT. Example: (n8n OR zapier) NOT wordpress. | Not needed |
| Sort Order | Ask Upwork for recent or relevant jobs. | Not needed |
| Maximum Job Age (hours) | Save jobs posted within this many hours before the run starts. 24 means one day; 0.5 means 30 minutes; 0 turns it off. | Not needed |
| Job type, experience, project length, hours, and rates or budget | Ask Upwork to narrow its search before returning jobs. | Not needed |
| Client Countries and Client Hiring History | Ask Upwork for jobs from selected client locations or clients with a chosen number of hires. | Not needed |
| Contract-to-Hire Only | Find jobs that may lead to a full-time hire. | Not needed |
| Payment-Verified Clients Only and Proposal Range | Ask Upwork for verified clients or jobs in a proposal-count band. | Required |
Use a Custom Search URL for categories, client timezones, regions, or locations outside the form's country list. Previous-client matching and sorting by client spending or rating also work through supported search URLs and require authentication. Filtering by client location or hiring history does not unlock client values in the output.
The Actor saves the jobs Upwork returns, subject to job age, duplicate removal, and your run limits. It does not apply separate keyword, client-spending, rating, review-count, or proposal-count checks. Filter those values in your own workflow after delivery. Missing client values do not remove a returned job.
For more precise keywords, use Upwork's advanced search guidance. The Actor forwards your search expression without adding its own text-matching rules.
π Input guidance
- Keep the default Residential proxies for better reliability.
- A Custom Search URL replaces the query and all native search filters in the form, including client countries and payment verification. Job age and run limits still apply. Paste one HTTPS Upwork job-search URL, not an individual job URL.
- Unsupported URL filters produce an input error. Remove the unsupported setting or use the form's search controls.
- Only the marked search filters require authentication. Without valid access, payment verification, proposal bands, and previous-client matching stop with an error. Visitor-compatible filters still work without login; no filter is silently removed.
- The job-age cutoff stays fixed throughout a run, including retries and restarts. Jobs without a usable posting time cannot pass this filter. An older job can appear before newer jobs, even with recent sorting, so the Actor checks every job on each fetched page.
- Maximum Job Age stops after two consecutive pages with no fresh jobs, or at your page or result limit if reached sooner. A page with any job within the age range resets the count, even if that job is a duplicate. Saved results remain available. This limits wasted requests, but fresh jobs may still appear on later pages. The count is preserved across retries and restarts.
- An unavailable value is
null. Authentication does not guarantee every field. Basic searches may have fewer available jobs and pages.
Older saved tasks
Remove any active Include / Exclude Keywords, excluded countries, minimum client spending, rating, review count, or Maximum Proposals settings. These rules are no longer applied. Active retired rules produce a clear input error; they are not silently ignored. Hidden legacy custom rules also need to be removed. Use Maximum Job Age (hours) instead of the older maxJobAge setting. Use Proposal Range for Upwork's proposal bands rather than an exact maximum.
Project Length is supported in both the search and results. Native filters use Upwork's matching rules. A job returned by Upwork will not be discarded because the Actor interprets its budget, workload, or client information differently. Every delivered job is a paid result, even if your workflow later discards it.
π 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 visitor results when your selected filters support visitor access. Searches with authentication-only filters stop instead. 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. With Maximum Job Age enabled, two consecutive pages with no fresh jobs end the search early. Fewer than 50 returned jobs also ends the search. The returned page size is checked before filters.
- Maximum Results: Limits saved jobs after the job-age check and duplicate removal. It does not guarantee that enough jobs are available.
- Run time: New requests stop after one hour, including retries and restarts. Current requests and saves may finish afterward.
- Connection attempts: Each run allows up to three browser attempts, including retries and restarts. Repeated connection failures stop the run. Any saved jobs remain available.
- Spending limits: The remaining spending allowance limits saved jobs. With Extra Details enabled, the Actor budgets for the result fee and any active enrichment fee before fetching details. A small remaining allowance may stop the run before it reaches your result limit.
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.
Each saved job counts as one result. With Add Extra Details enabled and an enrichment fee active for your run, each saved job with usable Extra Details also has that fee. The job stays in one row; it is not saved a second time. Missing, empty, or failed details have no enrichment fee. Partial details can be charged when they contain usable information. Check the Actor's Pricing for current fees. Startup and any listed platform-usage charges also apply. 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 turn on Add Extra Details. 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. |