ParseForge Scrapers

Upwork Jobs Scraper - Client Spend & Job Alerts

parseforge/upwork-jobs-scraper

JobsLead generationAutomation

Scrape Upwork jobs with the client panel a logged-out visitor sees: spend, hires, rating, reviews, member since, city and industry, plus exact proposal counts and job activity. No login. Job alerts with incremental mode. CSV, JSON, Excel.

Run this scraper See the API call
Total runs
4
Bookmarked
0
Last modified
2 days ago

This scraper was last updated on .

What does the Upwork Jobs Scraper - Client Spend & Job Alerts return?

ParseForge Banner

Upwork Jobs Scraper & API: Client Spend, Hires, Proposals & Job Alerts

Scrape Upwork job postings with the client behind every job, exactly as Upwork shows it to a logged-out visitor: total spent, hires, active hires, hours, rating, reviews, member since, city, industry and company size, plus the exact proposal count, interviews and invites. 300 postings came back in 26 seconds in our last test run, with no login, no cookies and no browser. Export to CSV, JSON, Excel or XML, run it as an Upwork jobs API, or schedule it as a job alert that only returns what is new.

Upwork had 106,959 open job postings on September 28, 2026. Its search shows them one page at a time, puts the client's details one click away on each job, and Upwork retired its job RSS feeds in 2024. This Actor reads only what Upwork publishes to logged-out visitors: its public job search and its public job pages. It applies Upwork's own filters and returns one flat row per job: 66 fields with the public job page (the default), 42 in the faster basic depth.

Who uses it What they scrape Upwork jobs for
Freelancers and agencies Job alerts for their niche every few minutes, with the client's spend, hires and rating already on the row, so Connects go to clients who hire and pay
Agency business developers A daily list of companies outsourcing what the agency sells, with city, industry, company size and lifetime spend
Lead-generation and sales teams Companies with a live need and a budget, from the category or skill they serve
Market and rate researchers Hourly rates and fixed budgets by skill, category, experience level and client country
Recruiters and staffing firms Contract demand by skill and level, and which clients hire repeatedly
Data and AI teams Job-description corpora with Upwork's own category, specialty and skill labels

What it does

The Actor takes search keywords, Upwork job-search URLs and job URLs, alone or together, and returns one row per job posting, de-duplicated on the job ID across every keyword and URL in the run.

  • ๐Ÿ‘๏ธ Only what a logged-out visitor sees: the public job search and the public job page, read with the same visitor access a browser gets without an account. No login, no session, no members-only data, and no names or profile links of freelancers or other people.
  • ๐Ÿ”Ž Search like upwork.com: keywords, newest-first or most relevant, and every filter Upwork's job search offers: payment type, experience level, 12 categories and 64 subcategories, hourly rate, fixed budget, number of proposals, payment-verified clients, client location (206 regions and countries), client hiring history and contract-to-hire.
  • ๐Ÿ”— Paste any search URL: set your filters on upwork.com, copy the address bar and paste it. Every filter in the link is applied, however long the link is.
  • ๐Ÿ’ผ Job facts, pre-parsed: title, URL, job ID, posted and created time to the millisecond, renewal time, payment type, budget or hourly range as numbers with currency, experience level, project length in words and weeks, workload, freelancers needed, skills and the full description.
  • ๐Ÿข The client on every row: country and country code, payment verification, lifetime spend, rating and number of reviews, straight from the search.
  • ๐Ÿงพ The public job page, on by default: client city, timezone, total hires, active hires, hours billed, member since, industry and company size; category, subcategory, specialty, project type and the contract-to-hire badge; interviews, invites sent, unanswered invites, hires on this job and the client's last activity; freelancer requirements (English level, minimum Job Success, Rising Talent, preferred locations and freelancer type).
  • ๐Ÿ”” Incremental mode for job alerts: each run returns only the jobs that appeared since the previous run with the same input, plus recent ones whose title, description, budget, level or length was edited. Jobs you already have are skipped and never charged, and the run stops paging once it reaches the previous run.
  • โฑ๏ธ Exact time windows: "posted within the last N hours" is checked on each job's publish time, and with newest-first sorting the run stops paging once the listing is past the window.

What you can do with Upwork job data

๐Ÿ”” Send new Upwork jobs to Slack or email, before the proposals pile up.

Schedule the Actor every 15 minutes with your keywords, incrementalMode: true and proposalsRanges: ["0-4", "5-9"]. Each run returns only the jobs that appeared since the last one. In the Actor's Integrations tab, connect Slack (post each new row to a channel), email (the run's results as an attachment), Google Sheets, or a webhook to Make or Zapier. A run that finds nothing new delivers nothing and only costs its start fee.

๐Ÿงฒ Build an agency lead list every morning.

Search the categories your agency sells, keep clientPaymentVerifiedOnly, clientMinTotalSpent: 5000 and clientHires: ["10-"], and read clientCity, clientIndustry, clientCompanySize, clientMemberSince, clientTotalHires and clientActiveHires on each row. A client who spent $22,990, hired 24 freelancers and has 12 active right now is a very different lead from a first-time poster, and the row tells you which one you have.

๐ŸŽฏ Qualify a client before you spend Connects.

Sort by clientRating, clientReviews, clientTotalSpent and clientTotalHours, and check interviewing and clientLastActivity to see whether the client is still reviewing proposals.

๐Ÿ“ˆ Research rates and budgets.

Pull a few thousand postings per skill or subcategory with dataDepth: "basic" and compare salaryMin, salaryMax and salaryInterval by experience level, client country and project length.

Why choose this scraper

What you get
Public data only It reads what Upwork shows a logged-out visitor, nothing a member login unlocks. There is no Upwork account to hand over, no session to get flagged, and no personal data of freelancers in the output.
The client panel, flat Spend, rating, reviews and payment verification on every row; city, timezone, hires, active hires, hours, member since, industry and company size from the public job page, as plain columns ready for a spreadsheet.
Job alerts built in Incremental mode remembers what each input already delivered and returns only new or changed jobs, then stops paging once it has caught up.
Exact proposal counts The real number, not only the bucket, so you can sort by competition.
Any search URL works Paste the link from your browser, filters and all. Unknown parameters are listed in the run log instead of silently changing your results.
Filters applied by Upwork Payment verification, proposals, category, budget, rate, location and hiring history narrow the search itself, then the live values are checked again, because Upwork's filter index can trail a new proposal by a minute.
Built not to lose job pages Upwork answers 429 after about 100 job pages from one IP. The Actor spreads job pages over a small pool of IPs and retires each one before it hits the limit: none lost to rate limits in our 300-job test runs.
Pay only for what you keep Filtered-out, duplicate, unchanged and error rows are never charged, and there is no minimum per run.
One jobs schema Rows use the ParseForge jobs-1 names (jobId, uid, salaryMin, datePosted, descriptionText) shared with our other jobs Actors, so Upwork merges with career-site and job-board data without renaming.

How it compares

All five Actors below scrape Upwork job postings. The comparison uses each rival's public input options and Store price on September 28, 2026 (price on the Free plan tier, per 1,000 jobs).

Feature ParseForge neatrat/upwork-job-scraper blackfalcondata/upwork-scraper memo23/upwork-jobs-scraper-ppe flash_mage/upwork
Data source Only what a logged-out visitor sees Its own logged-in cookies (yours optional) Public listings; your session token for detail fields Public data plus a database refreshed every 6 hours Public by default; optional login caps a run at 500 jobs
Client spend, rating, payment verified Flat columns on every row Yes Yes Nested JSON Nested JSON
Client city, hires, hours, member since, industry, size Flat columns, on by default Hires and hire rate Only with your own session token Assignments and spend In a nested buyer object
Exact proposal count Yes Proposals field Yes Yes Yes
Only new or changed jobs per run Yes No Yes Yes No
Paste a search URL Yes, every filter Yes Yes Yes No
Minimum billed per run None 10 jobs None stated None stated None stated
Price per 1,000 jobs $3.15 ($2.90 on higher plans) $3.50 ($3.20) $1.00 $0.99 plus its add-on $3.00 plus proxy events
Run start $0.02 None $0.001 $0.005 $0.001

The honest read: blackfalcondata and memo23 cost less per job, and the leader's logged-in cookies unlock fields a visitor cannot see (such as jobs posted and hire rate). What this Actor offers instead is the full public client panel as flat columns on every row, with no Upwork login involved at any point, live data, the job page on by default, job alerts, and no minimum per run. Against the most-used Upwork job scraper it is cheaper per job, and an alert run that finds nothing new costs $0.02 instead of 10 billed jobs.

What users of other Upwork scrapers asked for

Two complaints show up in the 1-star reviews of the most-used Upwork job scraper on Apify. This Actor was built to answer both.

  • "It was great until they changed it to a pay per results pricing which is absurd and not sustainable." Here you pay per job actually delivered, $0.00315 each, with no minimum per run. Filtered, duplicate and error rows are free, and in incremental mode jobs you already received are free too, so a scheduled alert pays only for new jobs plus a $0.02 start. The run stops cleanly at the spending cap you set.
  • "The Actor is not able to scrape using URL of complex search terms." Paste the full address of any Upwork job search in startUrls. The query and every filter in it (t, contractor_tier, hourly_rate, amount, client_hires, location, category2_uid, subcategory2_uid, occupation_uid, ontology_skill_uid, payment_verified, proposals, duration_v3, workload, contract_to_hire, sort) are read and applied. A parameter that is not a job-search filter is named in the log.

What an Upwork job looks like

A row with the public job page (the default), from a test run on September 28, 2026 (description trimmed):

{
  "title": "LinkedIn Ghostwriter & Newsletter Writer for Luxury Fragrance House and Founder",
  "jobUrl": "https://www.upwork.com/jobs/~022104673441735856616",
  "jobId": "2104673441735856616",
  "uid": "upwork:2104673441735856616",
  "status": "active",
  "jobType": "Hourly",
  "experienceLevel": "Expert",
  "category": "Writing",
  "subcategory": "Sales & Marketing Copywriting",
  "specialty": "Sales Copywriting",
  "projectType": "Ongoing project",
  "contractToHire": "No",
  "hasSalary": "Yes",
  "salaryText": "$35 - $75 per hour",
  "salaryMin": 35,
  "salaryMax": 75,
  "salaryCurrency": "USD",
  "salaryInterval": "hour",
  "salarySource": "board-structured",
  "projectLength": "1 to 3 months",
  "projectLengthWeeks": 9,
  "workload": "Part time",
  "freelancersNeeded": 1,
  "datePosted": "2026-09-28T20:44:55.414Z",
  "dateCreated": "2026-09-28T20:43:46.544Z",
  "dateRenewed": "Not Disclosed",
  "proposalsCount": 8,
  "proposalsRange": "5 to 10",
  "interviewing": 0,
  "invitesSent": 0,
  "unansweredInvites": 0,
  "hiredOnThisJob": 0,
  "clientLastActivity": "2026-09-28T21:24:31.275Z",
  "clientCountry": "United States",
  "clientCountryCode": "US",
  "clientCity": "Pooler",
  "clientTimezone": "America/New_York (UTC-04:00)",
  "clientPaymentVerified": "Yes",
  "clientTotalSpent": 22990.39,
  "clientRating": 5,
  "clientReviews": 9,
  "clientTotalHires": 24,
  "clientActiveHires": 12,
  "clientTotalHours": 1220,
  "clientMemberSince": "2024-12-27T00:00:00.000Z",
  "clientIndustry": "Fashion & Beauty",
  "clientCompanySize": 1,
  "requiredEnglishLevel": "Any level",
  "minJobSuccessScore": "Not Disclosed",
  "risingTalentWelcome": "No",
  "preferredFreelancerType": "Any",
  "jobPageStatus": "Available",
  "applyUrl": "https://www.upwork.com/jobs/~022104673441735856616",
  "source": "upwork",
  "sourceType": "job-board",
  "employmentType": "Contract",
  "searchTerm": "copywriting",
  "schemaVersion": "jobs-1",
  "skillCount": 8,
  "descriptionLength": 3158,
  "descriptionSnippet": "LinkedIn Ghostwriter & Newsletter Writer for Luxury Fragrance House and Founder BB Boutique & Co. is a contemp...",
  "descriptionText": "LinkedIn Ghostwriter & Newsletter Writer for Luxury Fragrance House and Founder\n\nBB Boutique & Co. is a contemporary luxury fragrance house exploring...",
  "skills": ["Ghostwriting Services", "Marketing Copywriting Services", "Newsletter Writing", "LinkedIn Profile Headline & Summary", "LinkedIn Development", "LinkedIn Marketing"],
  "preferredFreelancerLocations": [],
  "scrapedAt": "2026-09-28T21:24:48.772Z",
  "error": null
}

A row in basic depth (dataDepth: "basic"), 42 fields straight from the search:

{
  "title": "Graphic Designer",
  "jobUrl": "https://www.upwork.com/jobs/~022104677239567151397",
  "jobId": "2104677239567151397",
  "uid": "upwork:2104677239567151397",
  "status": "active",
  "jobType": "Hourly",
  "experienceLevel": "Expert",
  "hasSalary": "Yes",
  "salaryText": "$20 - $45 per hour",
  "salaryMin": 20,
  "salaryMax": 45,
  "salaryCurrency": "USD",
  "salaryInterval": "hour",
  "salarySource": "board-structured",
  "projectLength": "More than 6 months",
  "projectLengthWeeks": 52,
  "workload": "Not Disclosed",
  "freelancersNeeded": 2,
  "datePosted": "2026-09-28T20:59:36.656Z",
  "dateCreated": "2026-09-28T20:58:52.075Z",
  "dateRenewed": "Not Disclosed",
  "proposalsCount": 1,
  "proposalsRange": "Less than 5",
  "clientCountry": "United States",
  "clientCountryCode": "US",
  "clientPaymentVerified": "Yes",
  "clientTotalSpent": 51655.61,
  "clientRating": 4.53,
  "clientReviews": 421,
  "applyUrl": "https://www.upwork.com/jobs/~022104677239567151397",
  "source": "upwork",
  "sourceType": "job-board",
  "employmentType": "Contract",
  "searchTerm": "logo",
  "schemaVersion": "jobs-1",
  "skillCount": 3,
  "descriptionLength": 226,
  "descriptionSnippet": "I'm looking for a graphic designer who can work on a various type of projects including logos, flyers, web ban...",
  "descriptionText": "I'm looking for a graphic designer who can work on a various type of projects including logos, flyers, web banners, and more. Please respond with your...",
  "skills": ["Adobe Photoshop", "Graphic Design", "Adobe InDesign"],
  "scrapedAt": "2026-09-28T21:27:38.927Z",
  "error": null
}

In incremental mode every row also says whether the job is new or changed, and when you first received it (excerpt):

{
  "changeType": "new",
  "firstSeenAt": "2026-09-28T16:42:52.972Z",
  "title": "Video Editor for Creator Content",
  "jobUrl": "https://www.upwork.com/jobs/~022104566968821102300",
  "datePosted": "2026-09-28T16:42:11.028Z",
  "jobType": "Hourly",
  "salaryText": "$8 - $18 per hour",
  "proposalsCount": 0,
  "clientCountry": "United Kingdom",
  "clientPaymentVerified": "Yes",
  "clientTotalSpent": 2076.38
}

A job whose page Upwork keeps for logged-in members keeps its search data and says so (excerpt):

{
  "title": "Minimalist Intimate Care Brand Identity",
  "jobUrl": "https://www.upwork.com/jobs/~022104668766908097584",
  "clientCountry": "United States",
  "clientPaymentVerified": "Yes",
  "proposalsCount": 22,
  "clientCity": "Not Disclosed",
  "clientTotalHires": "Not Disclosed",
  "jobPageStatus": "Members only"
}

A URL that cannot be read comes back as a free error row:

{
  "inputUrl": "https://www.upwork.com/jobs/~021850000000000000001",
  "errorCode": "JOB_NOT_FOUND",
  "scrapedAt": "2026-09-28T15:12:33.410Z",
  "error": "Upwork has no public job at this URL (closed, removed or mistyped)."
}

Values Upwork does not publish for a job read Not Disclosed (for example the budget of an hourly job posted without a rate, or the rating of a client with no reviews yet). Only error is ever null. Error codes: JOB_NOT_FOUND, JOB_RESTRICTED, JOB_PAGE_FAILED, INVALID_URL, SEARCH_FAILED, BLOCKED.

How often each field is filled

Measured on a 300-job run for "design" on September 28, 2026. 272 of the 300 job pages were public; 28 (9%) were members only and kept their search data. A field that is empty is usually empty on Upwork too, mostly because the client is new:

Field Filled
Exact proposal count 99% of jobs
Budget or hourly range 78% of jobs
Client payment verified 75% of jobs
Client total spent above zero 53% of jobs
Client rating (clients with reviews) 45% of jobs
Client member since 98% of public job pages
Client last activity 99% of public job pages
Client city 64% of public job pages
Client hires above zero 60% of public job pages
Interviews in progress 40% of public job pages
Client hours above zero 37% of public job pages
Client company size 20% of public job pages
Preferred freelancer locations 17% of public job pages
Client industry 15% of public job pages
Contract-to-hire 11% of public job pages

Configure the run

Mix keywords, search URLs and job URLs in one run. The Input tab lists every option; these are the common setups.

The default: newest Python jobs with the public job page, returned in seconds:

{ "searchTerms": ["python"], "maxItems": 20 }

A job alert every 15 minutes: only new or changed jobs, low competition, paying clients:

{ "searchTerms": ["n8n", "make.com", "zapier"], "incrementalMode": true, "proposalsRanges": ["0-4", "5-9"], "clientPaymentVerifiedOnly": true, "maxItems": 100 }

Paste a search you already set up on upwork.com, filters and all:

{ "startUrls": [{ "url": "https://www.upwork.com/nx/search/jobs/?q=shopify&t=1&amount=500-999,1000-4999&payment_verified=1&proposals=0-4,5-9&sort=recency" }], "maxItems": 200 }

An agency lead list: US clients with a hiring history and real spend:

{ "searchTerms": ["web design", "landing page"], "clientLocations": ["United States"], "clientHires": ["10-"], "clientMinTotalSpent": 10000, "clientMinRating": "4.5", "maxItems": 300 }

A rate benchmark for one subcategory (Web Development, 5,463 open jobs on September 28, 2026), expert hourly work, search data only:

{ "subcategories": ["531770282584862733"], "jobTypes": ["hourly"], "experienceLevels": ["ExpertLevel"], "hourlyRateMin": 30, "dataDepth": "basic", "maxItems": 1000 }

Everything posted in the last 24 hours in one category, without keywords:

{ "categories": ["531770282580668420"], "postedWithinHours": 24, "maxItems": 500 }

Read specific jobs by URL:

{ "startUrls": [{ "url": "https://www.upwork.com/jobs/~022104673441735856616" }, { "url": "https://www.upwork.com/freelance-jobs/apply/Design-and-format-Employee-handbook_~022104581160459179343/" }] }

Share one alert memory between two different inputs (or change the name to start over):

{ "searchTerms": ["react native"], "incrementalMode": true, "stateKey": "mobile-alerts", "maxItems": 50 }

With no keywords and no URLs, the run lists the newest postings across all of Upwork, with your filters applied.

Job alerts to Slack or email

  1. Open the Actor, set your keywords and filters, switch on Only new or changed jobs, and save the input as a task.
  2. In Schedules, run the task every 15 or 30 minutes.
  3. In the task's Integrations tab, add Slack (a message per run with the new rows), email (the dataset as an attachment when a run succeeds), Google Sheets (append rows), or a webhook to Make, Zapier or n8n for any other channel.

The first run delivers the newest maxItems jobs and sets the starting point; every later run delivers only what appeared since, plus edits to jobs listed shortly before the previous run. If a run hits maxItems or your spending limit, the starting point does not move, so the jobs it left out arrive in the next run. The memory lives in a key-value store named upwork-jobs-scraper-state on your own Apify account, one record per input.

Free users

Free-plan runs return up to 10 jobs as a preview. Upgrade your Apify plan to collect up to 1,000,000 jobs per run.

Run it

  1. Create a free Apify account with $5 in credit.
  2. Open the Upwork Jobs Scraper.
  3. Enter searchTerms or paste Upwork URLs in startUrls, pick your filters, and click Start.
  4. Export the results as CSV, Excel, JSON or XML from the Dataset tab (the Clients and Job alerts views show the most useful columns side by side), or schedule the run as a job alert.

Run it programmatically through the Apify API or the ApifyClient for JavaScript and Python.

Use with AI agents (MCP)

Give an AI agent live Upwork job search through the Model Context Protocol. Add the Actor to Claude, Cursor or any MCP client:

claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/upwork-jobs-scraper"

Then ask in plain language:

  • "Find Upwork jobs for n8n automation posted in the last 24 hours with fewer than 10 proposals, and list the five clients who spent the most."
  • "List Upwork clients in Germany who posted a design job this week, have spent more than $5,000 and have at least 10 hires."
  • "What hourly rates are Upwork clients offering for React Native developers at expert level?"

Copy this into ChatGPT, Claude or Cursor to start:

Use the Apify Actor "parseforge/upwork-jobs-scraper" to search Upwork job postings. Input: { "searchTerms": ["<keyword>"], "postedWithinHours": <hours>, "proposalsRanges": ["0-4"], "clientPaymentVerifiedOnly": true, "maxItems": <n> }. Jobs come back with title, jobUrl, datePosted, jobType, salaryMin, salaryMax, proposalsCount, clientCountry, clientCity, clientTotalSpent, clientRating, clientTotalHires, clientMemberSince and descriptionText. Call it with the ApifyClient and my APIFY_TOKEN.

Only what a logged-out visitor sees

The Actor reads Upwork's public job search and public job pages with the same visitor access any browser gets without an account. It never logs in and never uses anything a member login unlocks. Upwork's own job page leaves these out for logged-out visitors, so no row carries them:

  • The client's name or company name.
  • Jobs posted, hire rate, open jobs and average hourly rate paid. Upwork shows these to members only.
  • Screening questions, the client's past contracts and the reviews on them. Members only.
  • Connects needed to apply, attachments and other applicants' bids. Members only.
  • Jobs Upwork keeps for members. Their rows keep the search data and say Members only in jobPageStatus (9% of jobs in our 300-job test).

Rows never contain the name or profile link of a freelancer or any other person.

Troubleshooting

Why am I getting no results?

The filters may exclude everything: Upwork applies them together, so a narrow keyword plus a proposals range plus a location can return zero. The run log prints how many postings Upwork reports for each search before anything else; loosen one filter at a time. In incremental mode, an empty run means nothing is new since the last run with the same input.

Why fewer results than I asked for?

Your filters, the postedWithinHours window, incremental mode or the 5,050-postings limit of one search ended the run first. Add keywords or split the search by category or budget to go wider.

What does jobPageStatus mean?

Available when the public job page was read. Members only when Upwork keeps that page for logged-in members; the row keeps all search data. Removed when the job closed between the search and the page read. Not loaded when Upwork refused the job page after several fresh sessions; the row keeps all search data.

Why is the client timezone far from the client city?

clientTimezone is the timezone set in the client's Upwork profile, exactly as Upwork reports it, and some clients never change it.

Why does a posting have a dateRenewed?

The client renewed an older posting, so Upwork lists it with the newest jobs again. datePosted keeps the original publish time, and the time window is checked on that.

FAQ

Question Answer
Do I need an Upwork account, cookies or an API key? No. It reads only Upwork's public job search and public job pages, what a logged-out visitor can see.
Does it use anything that needs an Upwork login? No. Nothing a member login unlocks is read, and the Actor never logs in.
Does it collect personal data of freelancers? No. Rows contain no freelancer names or profile links.
Is this an Upwork jobs API? It works like one: call the Actor through the Apify API with JSON input and get JSON rows back, without applying for Upwork's official API.
Can I use it for Upwork job alerts? Yes. Switch on incremental mode and schedule it; each run returns only new or changed jobs, and you can send them to Slack, email, Sheets or a webhook.
Does it replace the old Upwork RSS feeds? Yes, and with more: filters, the client's spend, hires and rating, and exact proposal counts.
Can I paste my Upwork search URL? Yes, with every filter in it. Several URLs can run in one go.
What is the difference between full and basic depth? Full (the default) also reads each public job page: client city, hires, active hires, hours, member since, industry, company size and the job's activity. Basic reads the search only and is about 4 times faster. Same price.
Why no hire rate or jobs posted? Upwork shows those to logged-in members only, so they are out of scope. clientTotalHires, clientActiveHires and clientTotalHours are public and included.
How many jobs per run? Free plan: 10. Paid: up to 1,000,000, with up to 5,050 per search, so use several keywords or filters for bigger pulls.
How fast is it? 300 jobs in 26 seconds with the public job page, 300 jobs in 6 seconds in basic depth (our test runs on September 28, 2026).
How fresh is the data? Live: every run reads Upwork at that moment. Posting times are exact to the millisecond.
Where is the incremental memory kept? In a key-value store named upwork-jobs-scraper-state on your Apify account. Delete a record, or change stateKey, to start over.
Is this an official Upwork product? No. It is unofficial and reads only publicly available data.

Next step

Found the jobs? Find the people who can do them. Upwork Freelancers Scraper searches Upwork's public freelancer directory by skill and returns hourly rate, earnings, Job Success score, badges, location and agency for each profile, so you can go from a job and its client to the freelancers who fit it.

๐Ÿ†˜ Need help? Open our contact form or email parseforge@protonmail.com with your run ID, your input and what you expected.

โš ๏ธ Disclaimer. This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by Upwork Global Inc. It collects only data Upwork publishes to logged-out visitors on its public job search and job pages, and its rows contain no personal data of freelancers. You are responsible for using the data in compliance with Upwork's terms and applicable laws, including GDPR and CCPA.

What input does the Upwork Jobs Scraper - Client Spend & Job Alerts accept?

FieldTypeWhat it doesDefault
searchTerms array Keywords as you would type them in Upwork's job search, one search per line (for example python, shopify, logo design). Results are merged and de-duplicated on the job ID. Leave empty, with no URLs below, to list the newest postings across all of Upwork. ["python"]
startUrls array Optional. Paste job links (https://www.upwork.com/jobs/~02...) to read those postings, or job-search links copied from your browser after setting filters on upwork.com/nx/search/jobs (every filter in the link is applied, including category, budget, proposals and payment verified). The filters in this form do not apply to pasted URLs. not set
maxItems integer Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000 20
dataDepth string (2 options) Full is the default. Basic is several times faster for very large pulls. full
incrementalMode boolean For scheduled job alerts. The first run delivers the newest jobs and sets the starting point; every later run with the same search input returns only the jobs that appeared since, plus recent ones whose title, description, budget, level or length was edited. Jobs you already have are skipped and never charged. The memory is kept in a key-value store named upwork-jobs-scraper-state on your own account. false
stateKey string Optional. Runs with the same name share one memory, even when their inputs differ. Change it to start over. Leave empty to key the memory on the search input. not set
sortBy string (2 options) Newest first also lets the posted-within window stop paging early. recency
jobTypes array Leave empty for both. not set
experienceLevels array Leave empty for all levels. not set
categories array Upwork's 12 top-level job categories. not set
subcategories array Upwork's 64 subcategories. Pick a subcategory without its category to stay narrow. not set
hourlyRateMin integer Hourly jobs whose rate range reaches at least this. Fixed-price jobs pass through unless you also pick Hourly as payment type. not set
hourlyRateMax integer Hourly jobs whose rate range starts at or below this. not set
fixedBudgetMin integer Fixed-price jobs with at least this budget. Hourly jobs pass through unless you also pick Fixed price as payment type. not set
fixedBudgetMax integer Fixed-price jobs with at most this budget. not set
proposalsRanges array How many freelancers already applied. not set
postedWithinHours integer For example 1, 24 (one day) or 168 (one week). With newest-first sorting the run stops paging once postings get older, so a job alert every 15 minutes stays cheap. not set
clientPaymentVerifiedOnly boolean Only jobs from clients with a verified payment method. false
clientLocations array Regions, subregions or countries, spelled the way Upwork lists them. All 206 values were checked against the live search. not set
clientHires array How many freelancers the client has hired before. not set
clientMinTotalSpent integer Skips clients who spent less on Upwork, or who hide their spend. not set
clientMinRating string For example 4.5. Skips clients below it and clients with no reviews yet. not set
contractToHireOnly boolean Only postings the client marked as possible full-time hires. false
proxyConfiguration object Optional. Set it only to force a proxy group or country. {"useApifyProxy":false}

How much does the Upwork Jobs Scraper - Client Spend & Job Alerts cost?

from $2.90 per 1,000 results

Charged forWhat it isPrice each
Actor Start Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). $0.02
Upwork job posting One job row in the dataset, with the client panel a logged-out visitor sees. Filtered, duplicate, unchanged and error rows are free. $0.0029 to $0.00315

Tiered: the lower figure is the price on a higher Apify plan. Billing and the free credit live on Apify.

How do I call the Upwork Jobs Scraper - Client Spend & Job Alerts API?

One POST returns the dataset directly. Same shape for every scraper in the library, so swapping the slug is the only change.

POST ยท run and get results
curl -X POST "https://api.apify.com/v2/acts/parseforge~upwork-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchTerms": [
      "python"
    ],
    "maxItems": 20,
    "dataDepth": "full",
    "incrementalMode": false,
    "sortBy": "recency"
  }'

What example inputs can I use?

Use these inputs to see how a run is configured.

input.json
{
  "searchTerms": [
    "python"
  ],
  "maxItems": 20,
  "dataDepth": "full",
  "incrementalMode": false,
  "sortBy": "recency"
}

What do users say about the Upwork Jobs Scraper - Client Spend & Job Alerts?

No reviews yet. Be the first.

How do I report an issue with the Upwork Jobs Scraper - Client Spend & Job Alerts?

We build and maintain this scraper, so a problem with it comes to us. Report it on the Apify listing and the thread stays attached to the scraper where the next person can find it: open an issue.

Broken and urgent, or you would rather not post in public? Write to parseforge@protonmail.com and it reaches the people who wrote it.

What related scrapers can I use?

Run Upwork Jobs Scraper - Client Spend & Job Alerts on Apify All scrapers