ParseForge Scrapers

Upwork Freelancers Scraper - Hourly Rate & Earnings

parseforge/upwork-freelancers-scraper

JobsLead generation

Scrapes Upwork freelancer profiles by skill keyword. Returns a flat row with title, hourly rate, total earnings, job success score, and location.

Run this scraper See the API call
Total users
416
Monthly active
72
Total runs
3.4K
Bookmarked
2
Rating
5.0 (1)
Last modified
2 days ago

This scraper was last updated on .

What does the Upwork Freelancers Scraper - Hourly Rate & Earnings return?

ParseForge

Upwork Freelancers Scraper

Scrape Upwork freelancer profiles by skill, keyword, location, or a pasted Upwork search URL. Each profile returns a permanent freelancer ID, the title, hourly rate, total earnings, job success score, hours and jobs worked, location, intro video link, and agency. No login or API key. Export to CSV, JSON, Excel, or XML.

Pay only for results: there is no start fee today, only a price per freelancer. From 3 October 2026 a run also carries the standard Apify start fee of $0.005 per GB of run memory, which is $0.005 per run at the default 1 GB.

Upwork's official API requires a developer account and restricts the depth of freelancer data you can pull. This actor reads the public search results directly, filtering by earned amount (including new freelancers with no earnings yet), hourly rate, job success, hours billed, Top Rated and Rising Talent badges, or specific countries and regions, and returns each matching profile in one consistent schema. Build a talent pipeline, analyze competitor skill sets, or populate a recruitment database without writing a single line of code.

Who uses it What they scrape Upwork for
Recruitment agencies Build a searchable database of pre-vetted freelance talent for specific skill sets.
Market analysts Track the supply and hourly rates of freelancers in a given niche over time.
Sales teams Identify and qualify independent contractors who may need complementary tools or services.
Aspiring freelancers Benchmark their own rates and skills against top earners in their category.

What it does

This Actor collects Upwork freelancer profiles by skill keyword and returns each one as a flat row with their title, rate, earnings, and location.

  • ๐Ÿ”— Search URL input: build a search on upwork.com, paste its address, and the actor applies the same keyword and filters.
  • ๐ŸŒฑ Earned amount filter: find new freelancers with no earnings yet, or only those past $1, $100, $1k or $10k earned.
  • ๐Ÿ’ฒ Rate, job success and hours: set a minimum or maximum hourly rate, a minimum Job Success Score, or a minimum of hours billed.
  • โญ Badge filters: restrict results to Top Rated, Top Rated Plus, or Rising Talent freelancers.
  • ๐ŸŒ Location targeting: filter by continent, sub-region, or a specific country to find local talent.
  • ๐Ÿ” No repeats across runs: turn on "Skip freelancers from earlier runs" and a repeated search returns only profiles you have not collected yet.
  • ๐Ÿ†” Stable freelancer ID: every row carries Upwork's ~01... freelancer ID, which stays the same when a freelancer changes the username in their profile link.
  • ๐Ÿข Agency details: freelancers who belong to an agency come with the agency ID, name and page URL, plus every agency they are in.
  • ๐ŸŽฌ Intro video: the YouTube link from the profile's video introduction, when the freelancer has one.
  • ๐Ÿ”ข Volume control: set a precise maximum number of profiles to collect. Upwork shows at most 10,000 results per search, so larger pulls use several keywords in one run.
  • ๐Ÿ™ˆ Honest nulls: when a freelancer hides their earnings, Upwork reports $0. The actor returns totalEarnings: null instead of a false $0, with earningsHidden: true when the profile's hours, Job Success Score or badge prove the earnings are hidden. A missing Job Success Score is null, not 0.

Results export to CSV, JSON, Excel, or XML, or straight from the API.

What you can do with Upwork data

๐Ÿ” Build a talent pipeline.

A recruiter runs the actor daily for 'react developer' and filters by Top Rated Plus to maintain a fresh list of elite candidates.

๐Ÿ“Š Analyze freelance market rates.

A market analyst scrapes 'python developer' across different regions to compare average hourly rates and inform a pricing report.

๐ŸŒŽ Find local contractors.

A project manager sets the country filter to 'Canada' and the skill to 'technical writer' to find nearby freelancers for an on-site contract.

๐ŸŒฑ Reach new freelancers first.

A tool vendor pastes https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0 to list US copywriters who have not landed a paid job yet, and offers them an onboarding deal.

๐Ÿ” Work through a talent pool in batches.

An outreach team pulls 1,000 new copywriters on Monday and another 1,000 on Tuesday with the same search and history name. Tuesday's run leaves out everyone Monday already delivered, so nobody gets contacted twice.

๐Ÿ“ˆ Monitor competitor skills.

A freelancer scrapes their own niche to see which complementary skills top earners list and updates their own profile accordingly.

Why choose this scraper

What you get
No API registration Access public freelancer data without a developer account or OAuth tokens.
Fixed flat schema Every profile is normalized into the same columns for easy analysis.
Flexible location filters Target freelancers by continent, sub-region, or a single country.
Quality signals Filter by Top Rated and Top Rated Plus badges to isolate high-quality talent.

How it compares

This actor focuses exclusively on freelancer profiles, while the competitors listed below are designed for scraping Upwork job postings.

Feature ParseForge Upwork Job Scraper Upwork Job Extractor โšก Upwork Jobs
Scrapes freelancer profiles Yes Not listed Not listed Not listed
Scrapes job postings Not listed Yes Yes Yes
Filter by Top Rated status Yes Not listed Not listed Not listed
Filter by freelancer location Yes Not listed Not listed Not listed
Returns freelancer hourly rate Yes Not listed Not listed Not listed

Configure the run

Drive the Actor with a skill or job title keyword, and apply Top Rated and location filters as each profile is read so only matches reach your dataset. The Input tab lists every parameter.

A first run with the defaults:

{
  "searchQuery": "python developer",
  "maxItems": 10
}

Several keywords at once: separate them with commas. Each keyword is searched on its own and the results are merged, so every freelancer is returned once even when two keywords both match them.

{
  "searchQuery": "full stack developer, frontend developer, software engineer",
  "maxItems": 100
}

Paste a search you built on upwork.com. Keyword (q), location (loc), earned amount (revenue), hourly rate (hourly_rate), job success (nss), hours billed (hours) and the Top Rated, Top Rated Plus and Rising Talent badges carry over:

{
  "searchUrl": "https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0",
  "maxItems": 100
}

Or set the same filters by hand:

{
  "searchQuery": "copywriting",
  "country": "United States",
  "earnings": "none",
  "maxItems": 100
}

Run the same search again later without getting anyone twice. Every run that uses the same history name skips the freelancers earlier runs delivered:

{
  "searchUrl": "https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0",
  "maxItems": 1000,
  "skipPreviouslyScraped": true,
  "historyName": "us-copywriters-new"
}

A larger pull:

{
  "searchQuery": "python developer",
  "maxItems": 200
}

Free users

Free-plan runs return up to 100 results as a preview. Upgrade your Apify plan to lift that cap.

Run it

  1. Create a free Apify account with $5 in credit.
  2. Open the Upwork Freelancers Scraper.
  3. Set your inputs and any filters, then click Start.
  4. Export the results as CSV, Excel, JSON, or XML from the Dataset tab.

Run it programmatically through the Apify API (run-sync-get-dataset-items) or the ApifyClient for JavaScript and Python.

Use with AI agents (MCP)

Give an AI agent live access to Upwork 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-freelancers-scraper"

Then prompt it in plain language to run the scraper and read back the results.

Troubleshooting

Why am I getting no results?

Check that your searchQuery is spelled correctly and is a common term on Upwork. Also, try disabling the Top Rated or location filters, as they may be too restrictive for your chosen keyword. The run's status message says which search came back empty, and a run that ends with a warning instead of rows always names the reason.

I pasted a freelancer's profile link and got no data.

upwork.com/freelancers/~01... is one person's profile page, not a search. This Actor reads Upwork's talent directory, so paste a talent search address (https://www.upwork.com/nx/search/talent/?q=...) or type the skill in "Skill or job title keyword". The run says so in its status message rather than failing.

Why is the actor running slowly?

The actor respects Upwork's pages to avoid blocks. If you are collecting a very large number of profiles, the run will naturally take longer. Try reducing the maxItems for a faster test.

Why did the log say some search URL filters were skipped?

Upwork only offers some filters to signed-in clients, English level (english) among them. The actor reads the public search, so it applies every filter the public search supports, skips the rest, and lists the skipped ones in the log.

Why does an earned amount search take longer?

Upwork does not filter by earnings for visitors, so the actor reads the matching profiles in order and keeps the ones in your bracket. New freelancers tend to sit deeper in the results. You pay only for the profiles that match; a narrower keyword or location finishes faster.

Why did a run with "Skip freelancers from earlier runs" return fewer profiles than I asked for?

The history leaves out everyone earlier runs with the same history name already delivered. Once most matches have been collected, few new ones are left, and Upwork shows at most 10,000 results per search. Broaden the keyword or location, or use a new history name to start over.

Why are my location filters being ignored?

Only one location filter can be used at a time. If you set a country, the region and sub-region filters are ignored. The 'US Only' checkbox is also ignored when any other location filter is set.

Why do some profiles have missing data fields?

Not all freelancers make their full profile public. When a freelancer hides their earnings, Upwork's search still sends $0, so the actor returns totalEarnings: null and earningsHidden: true (about 1 in 5 experienced freelancers in our tests). totalEarnings is also null, with earningsHidden: false, when Upwork reports $0 for a freelancer who has jobs but no billed hours, because the search cannot tell an unpaid first job from hidden earnings. jobSuccessScore is null for freelancers who have no score yet or hide it. Other fields are null when Upwork sends nothing for them.

I am getting an error about the input schema.

Ensure your maxItems is a whole number between 1 and 1,000,000. Also, verify that any country or region name you entered matches the exact spelling from the dropdown list.

FAQ

Question Answer
Can I scrape freelancers by a specific skill? Yes. The searchQuery input accepts any skill or job title keyword, such as 'python developer', 'web scraping', or 'react'.
How do I filter for only US-based freelancers? Enable the 'US Only' checkbox. This filter is ignored if you also set a region, sub-region, or country.
What is the difference between Top Rated and Top Rated Plus? Top Rated is a badge for proven freelancers. Top Rated Plus is a higher tier for top earners on large contracts. You can filter by either or both.
Can I combine location filters? No. Only one location filter can be active at a time. Choose either a region, a sub-region, or a specific country.
Does this actor scrape job postings? No. This actor scrapes freelancer profiles. A separate ParseForge actor for Upwork job postings is in preparation. For job postings on company career sites and job boards, see the jobs actors under Related actors.
How many profiles can I collect in one run? You can set the maximum from 1 up to 1,000,000 profiles per run using the maxItems input.
Can I paste an Upwork search URL? Yes. Put the address of a talent search from upwork.com in the searchUrl input. Its keyword, location, earned amount, hourly rate, job success, hours billed and badge filters replace the matching fields.
How do I find new freelancers with no earnings? Set Earned amount to 'No earnings yet', or paste a search URL that has revenue=0. Upwork reports $0 both for new freelancers and for those who hide their earnings. Freelancers with no work history come back with totalEarnings: 0. Profiles with hidden or unknown earnings come back with totalEarnings: null, so keep only the rows where totalEarnings is 0 if you want strictly new freelancers.
How do I avoid duplicates between runs? Turn on "Skip freelancers from earlier runs" and keep the same history name. The actor saves the ID of every freelancer it delivers in a key-value store in your Apify account and leaves them out of later runs. You are charged only for new profiles.
Can every run use the same history name? Yes, that is how it is meant to be used. Keep the same name on every run and each one skips everyone the earlier runs delivered. Use a different name only when you want a separate list.
How do I reset the history? Use a new history name, or delete the key-value store with that name under Storage in Apify Console.
Can I filter by English level? Not yet. Upwork only offers the English level filter to signed-in clients, so it is skipped and noted in the log.
Do I need an Upwork account to use this? No. The actor reads publicly available search results and does not require a login or API key.
What data fields does the actor return? It returns a flat row of 36 fields for each freelancer, including their freelancer ID, name, title, description, hourly rate, total earnings, job success score, hours and jobs worked, Top Rated status, skills, city, country and timezone, intro video link, and agency.
How is the Job Success Score written? jobSuccessScore is Upwork's own 0 to 1 fraction (1 means 100%, 0.97 means 97%), and jobSuccessPercent is the same score as the whole percent shown on Upwork. Both are null when the freelancer has no score or hides it.
Which field should I use as a key? freelancerId (the ~01... ID). The username in profileUrl can change; the ID does not. personId is Upwork's numeric ID for the same person, sent as text so no digits are lost.
What agency data is included? agencyId (~01...), agencyOrgId (numeric), agencyName and agencyUrl for the freelancer's first agency, and an agencies list with the ID, name, URL, tagline and logo of each agency they belong to. Freelancers without an agency have these empty.
Where is the YouTube video? In videoUrl: the link a freelancer added as their profile's video introduction. It is empty when they have none. Links written inside the description text stay in description.
Can I export the results to Excel? Yes. The dataset can be exported in CSV, JSON, Excel, or XML formats directly from Apify.
How do I avoid getting blocked? The actor runs on the Apify platform with built-in proxy rotation to help ensure reliable data collection.

Next step

Each row carries the fields that these ParseForge jobs Actors take as input:

  • Salaries for the same skill. Look up a job title from title in Levels.fyi Salary Scraper to compare freelance hourlyRate with base, stock and bonus pay at tech companies.
  • Full-time demand for the same skill. Put a skill from skills into searchQuery of Indeed Jobs Scraper to set freelance hourlyRate against the salary ranges employers post for that skill.
  • Companies hiring that skill in-house. Put the same skill into searchTerms of Career Site Jobs Scraper to find employers with open roles for it on their own career sites.

๐Ÿ†˜ Need help? 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 publicly available data. You are responsible for using the collected data in compliance with the source's terms of service and applicable data-protection laws, including GDPR, CCPA, and PIPL. Do not use it to collect personal data unlawfully.

What input does the Upwork Freelancers Scraper - Hourly Rate & Earnings accept?

FieldTypeWhat it doesDefault
searchUrl string Paste the address of a talent search on upwork.com (for example https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0). Its keyword, location, earned amount, hourly rate, job success, hours billed and badge filters replace the matching fields below. Filters that need an Upwork login, such as English level, are skipped and listed in the log. A single freelancer's profile address (upwork.com/freelancers/~01...) is not a search: the run reports it and uses the keyword below instead. not set
searchQuery string Search keyword for finding freelancers (e.g. 'python developer', 'web scraping', 'react'). Several keywords separated by commas run as separate searches and the results are merged, with each freelancer returned once. python developer
maxItems integer How many freelancers to collect per run. 10
skipPreviouslyScraped boolean Remember every freelancer this actor delivers and leave them out of later runs, so running the same search again returns only new profiles. You are charged only for the new ones. The history is kept in a key-value store in your Apify account under the name below. false
historyName string Name of the key-value store that holds the history (letters, digits and hyphens). Runs that share a name never return the same freelancer twice, even across different searches. Use a separate name per campaign, or delete the store in Storage to start over. upwork-freelancers-history
earnings string (6 options) Keep only freelancers in this earnings bracket. 'No earnings yet' finds new freelancers who have not been paid on Upwork. Upwork does not filter by earnings for visitors, so the actor reads the results in order and keeps the matches: narrow searches finish faster. not set
hourlyRateMin integer Only freelancers charging at least this hourly rate. not set
hourlyRateMax integer Only freelancers charging at most this hourly rate. not set
jobSuccessMin integer Only freelancers with at least this Job Success Score, from 0 to 100. not set
hoursMin integer Only freelancers who billed at least this many hours on Upwork. not set
topRatedOnly boolean Only show Top Rated and Top Rated Plus freelancers false
topRatedPlusOnly boolean Only show Top Rated Plus freelancers false
risingTalentOnly boolean Only show freelancers with the Rising Talent badge false
usOnly boolean Only show freelancers from the United States. Ignored when region, sub-region, or country is set. false
region string (6 options) Filter by continent. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'. not set
subRegion string (6 options) Filter by sub-region. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'. not set
country string (188 options) Filter by specific country. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'. not set

How much does the Upwork Freelancers Scraper - Hourly Rate & Earnings cost?

from $16.99 per 1,000 results

Charged forWhat it isPrice each
Result Item Charged once per result collected. $0.01699 to $0.02266
Actor Start Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). $0.0038 to $0.005

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 Freelancers Scraper - Hourly Rate & Earnings 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-freelancers-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchQuery": "python developer",
    "maxItems": 10,
    "skipPreviouslyScraped": false,
    "historyName": "upwork-freelancers-history",
    "topRatedOnly": false
  }'

What example inputs can I use?

Use these inputs to see how a run is configured.

input.json
{
  "searchQuery": "python developer",
  "maxItems": 10,
  "skipPreviouslyScraped": false,
  "historyName": "upwork-freelancers-history",
  "topRatedOnly": false
}

What do users say about the Upwork Freelancers Scraper - Hourly Rate & Earnings?

Rated 5.0 out of 5 across 1 review. Read them on Apify.

How do I report an issue with the Upwork Freelancers Scraper - Hourly Rate & Earnings?

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 Freelancers Scraper - Hourly Rate & Earnings on Apify All scrapers