Upwork Rate & Market Intelligence β€” Freelance Skill Rates avatar

Upwork Rate & Market Intelligence β€” Freelance Skill Rates

Pricing

from $475.30 / 1,000 skill benchmarks

Go to Apify Store
Upwork Rate & Market Intelligence β€” Freelance Skill Rates

Upwork Rate & Market Intelligence β€” Freelance Skill Rates

Benchmark any freelance skill on Upwork: live demand (open jobs), hourly & fixed rate distribution (median, p25, p75), hourly-vs-fixed split, experience-tier mix, posting freshness and adjacent skills. One clean row per skill.

Pricing

from $475.30 / 1,000 skill benchmarks

Rating

0.0

(0)

Developer

Vitalii Bondarev

Vitalii Bondarev

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

4

Monthly active users

2 days ago

Last modified

Categories

Share

Stop guessing what a freelance skill is worth. Give this Actor a list of skills and it returns one clean benchmark row per skill β€” live demand, the real rate distribution (median, 25th and 75th percentile, full range), the hourly-vs-fixed split, the experience level clients are actually hiring, how fresh the market is, typical engagement length, and the skills each one is hired alongside.

It is built for people who need to price and position, not scroll job feeds: freelancers setting their rate, agencies scoping a new service line, recruiters and talent teams benchmarking contractor cost, analysts tracking the freelance economy, and AI agents that need structured labor-market data on demand.


What you get β€” one row per skill

Each skill you pass in produces a single, decision-ready record. No raw-posting dump to clean up yourself β€” the Actor samples the live market and does the statistics for you.

FieldWhat it tells you
skillThe skill / keyword you benchmarked
demand_open_jobsLive demand β€” the total number of open jobs for this skill right now
sample_sizeHow many recent postings were sampled for the rate stats
hourly_median_usd / fixed_median_usdHeadline median rates, ready for a table
hourly_rate_usdFull hourly distribution: median, p25, p75, min, max, mean, count
hourly_min_usd / hourly_max_usdDistribution of the posted hourly band edges
fixed_budget_usdFull fixed-price budget distribution (same stats)
job_type_splitHourly vs fixed counts and shares β€” how this skill is usually contracted
experience_mixEntry / intermediate / expert counts + expert_share (how senior the demand is)
freshnessPostings in the last 24h / 7d / 30d, newest/oldest age, and an estimated posts-per-day velocity
engagement_weeksTypical project length distribution where stated
adjacent_skillsThe skills most often requested alongside this one (with counts and shares)
scraped_atISO timestamp of the run

Why the percentiles matter

A single "average rate" hides the market. The p25–p75 band tells you where the bulk of real jobs sit, so a freelancer knows whether their rate is competitive or leaving money on the table, and an agency knows what a project will actually cost to staff. The expert_share and experience_mix tell you who the demand is for β€” a skill that's 70% expert-level pays very differently from one that's mostly entry-level work.

Why the adjacency map matters

adjacent_skills is the quiet superpower: it shows what each skill is bundled with in real postings. If you sell "React" and the market keeps pairing it with "TypeScript" and "Next.js", that's your upsell and your positioning, straight from demand data.


Input

{
"skills": ["python developer", "react", "copywriting"],
"sampleSize": 100,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
InputTypeDefaultDescription
skillsarray of stringsβ€”One or more skills/keywords to benchmark. Each runs independently and yields one row.
sampleSizeinteger100Recent postings sampled per skill for the rate stats (10–500). Demand counts are always the full market total.
proxyConfigurationobjectRESIDENTIAL / USApify proxy used to reach the target. Billed to the run owner.

Tip: start with a handful of skills and sampleSize 100 for a fast, cheap read. Bump sampleSize toward 300–500 when you want tighter, more stable percentiles on a high-volume skill.


Example output (abridged)

{
"skill": "python developer",
"demand_open_jobs": 1880,
"sample_size": 100,
"hourly_median_usd": 38.0,
"fixed_median_usd": 750.0,
"expert_share": 0.41,
"hourly_rate_usd": { "median": 38.0, "p25": 25.0, "p75": 60.0, "min": 12.0, "max": 150.0, "count": 63 },
"job_type_split": { "hourly": 63, "fixed": 37, "hourly_share": 0.63, "fixed_share": 0.37 },
"experience_mix": { "entry": 18, "intermediate": 41, "expert": 41, "expert_share": 0.41 },
"freshness": { "posted_24h": 22, "posted_7d": 71, "est_posts_per_day": 9.4 },
"adjacent_skills": [ { "skill": "Django", "count": 31, "share": 0.31 }, { "skill": "AWS", "count": 24, "share": 0.24 } ]
}

How it works

The Actor reaches Upwork's public job search through the site's own visitor API. Upwork is a protected target β€” it requires a residential proxy for reliable access β€” so the Actor routes every request through the Apify RESIDENTIAL proxy on a sticky session, obtains a short-lived visitor token the same way the public site does, and then queries the public job-search endpoint for each skill. It samples the most recent postings (so the freshness and velocity numbers reflect the live market), computes the distributions, and writes one row per skill.

Only public job-posting data is collected β€” titles, descriptions, skills, budgets, experience tier, post time and the search-wide demand count. No client-account or applicant data is requested.


Pricing

This Actor is pay-per-result: you are charged per skill successfully benchmarked. A skill that returns no live postings is not charged. Apify platform/proxy usage during the run is billed to your own account by Apify, as with any Actor.


Common uses

  • Set your freelance rate against the real p25–p75 band for your skill.
  • Scope an agency service line β€” see demand, senior-share and typical project budget before you staff it.
  • Benchmark contractor cost for a hiring or finance team.
  • Track the freelance economy β€” run the same skill list on a schedule and watch demand and rates move.
  • Feed an AI agent structured, on-demand labor-market data via the Apify API or MCP.

FAQ

Does this need my Upwork login? No. It uses only the public job search; you never provide credentials.

Why a residential proxy? The target requires it for reliable access. It's the default and billed to your run.

Can I benchmark non-tech skills? Yes β€” pass any skill or keyword (copywriting, video editing, bookkeeping, voice over, …). The same benchmark is computed for all.

How fresh is the data? Every run is live. The freshness block tells you exactly how recent the sampled postings are.

Rate this Actor

If Upwork Rate & Market Intelligence saved you time, please rate it on the Apify Store. A rating takes a few seconds and helps other people find a working scraper. If something did not work, open an issue on the Actor page and we will fix it.

Usage statistics

This Actor creates a small, content-free summary at the end of each run. It is used only to monitor reliability and improve this Actor. A copy is saved as USAGE_STATS in your own Apify key-value store, so you can see the exact record created for your run.

Set disableUsageStats to true in the input to opt out. Nothing is sent then; your USAGE_STATS record only says that statistics were disabled.

Only these fields are recorded:

  • schema version, Actor name and build number;
  • UTC start and finish hour (not a precise timestamp);
  • run duration, number of results and time to the first result, each as a coarse range;
  • whether the result was empty, the end status, and an error type from a fixed list;
  • memory setting and counts of charged events;
  • names of the input fields you set, never their values;
  • the selected option for input fields that offer a fixed list of choices (for example a sort order).

We do not collect input text, search terms, URLs, domains, usernames, email addresses, names, proxy credentials, tokens, scraped records, output items, raw error messages, stack traces, or hashes of any of those values. Records are kept for no longer than 13 months, used only as aggregated operational statistics, and never sold or shared.

Additional fields (Phase 2)

This Actor also records your Apify user ID, whether Apify marks the account as paying, the size range of list inputs, the selected country when the input offers a fixed list of countries, and one category from a fixed Actor taxonomy. We use these fields only for aggregate reliability, repeat-use and cross-Actor analysis; reports suppress any cell with fewer than five distinct users.

The same disableUsageStats: true input flag turns these fields off too. The user ID is removed after 13 months; we do not export, sell, share, or attempt to re-identify this data.

Run-outcome signals (v2)

To learn whether a run did what it was asked to do, the record also holds a few more coarse ranges and yes/no flags. None of them contains content:

  • the result limit you asked for (a range, when the input has one) and what share of it was delivered;
  • results delivered per input item you listed (a range);
  • output quality as ranges: how fully the result fields were filled, the share of rows that look like errors, the share of duplicate rows, and how many different fields appeared. These are counted in memory while results are saved; no result content is kept;
  • how the run was started (console, API, schedule, webhook, another Actor);
  • how it ended: stopped by you, timed out, reached the requested limit, stopped by the charge limit, and how many times the platform moved the run;
  • if this Actor reports it: how many items to process worked or failed (ranges) and one failure reason from a fixed list;
  • a short code made from the names of the input fields you set, never their values.

Repeat-run fingerprint (v2)

When your Apify user ID is recorded (see above), the record also holds an 8-character one-way code made from your input (proxy settings left out) and this Actor's name. It only lets us see that the same account ran the same input again soon after an unsatisfying run; we never see the input itself. It is stored only in the database, never published, and reports use it in aggregate with the same five-user minimum. It is the one exception to the statement above that no hashes are collected, and disableUsageStats: true turns it off.