moxlade/guides/upwork api for freelancer data

Upwork API for freelancer data: what the official GraphQL API gives you, what it asks for, and the route that needs no approval

If you searched for an Upwork API to get freelancer data, there are two routes. The official one is a GraphQL API behind a reviewed key, with a talent search and a profile query for approved applications. The other is our actor on Apify, which answers from a census of 30,042 profiles with no application to file. This page states what each one is, from the official documentation as read on 2026-09-13 and from our own runs.

published 2026-09-13 · updated 2026-09-13

The official Upwork API, as documented

Read from Upwork's developer documentation on 2026-09-13 (upwork.com/developer/documentation/graphql/api/docs/):

  • One GraphQL endpoint: https://api.upwork.com/graphql. You register an application and obtain its client credentials ("consumer key and consumer secret").
  • Every key is reviewed. "Every new request for an API Key will be reviewed." The conditions listed: an Upwork account with a valid name, a valid address, a profile picture and an active, verified payment method; a statement of who you are (client, freelancer, agency owner or developer) and why you need a key; confirmation that the application stays within "the daily request limit of 40,000 API requests" and does not use Upwork's name, logo or brand colours. Accounts without a valid ID go through ID verification first.
  • Rate limit: "300 requests per minute per IP address", HTTP 429 beyond it.
  • Caching: "Caching is not allowed for more than 24 hours according to our Terms of Service."
  • Freelancer data: the reference lists a search query for public freelancer profiles (search { searchFreelancerPublicProfile }, permission "Freelancer Profile – Read And Write Access") returning records with id, title, description, short name, ciphertext and portrait, and talentProfile(personId) for a primary or specialized profile (permission "Talent Profile – Read And Write Access public"). Each query names the permission scope the key must carry.

So the official route is the right one when you are building for Upwork users on Upwork's terms — a client's own hiring tool, an agency's own dashboard — and can file the application, hold the scopes, and refresh within a day. It is not a route to a list you keep: the 24-hour caching rule says so.

The alternative: a census you query

Our actor answers the questions a recruiter, an agency or a market researcher actually has, without a key from Upwork:

access
an Apify account and its token; no application, no scopes
search
keyword plus rate band, JSS, badge, country, hours, jobs, earnings, hire-again, tenure, recency, skills; nine sort orders
per row
65 typed fields, including exact earnings where exposed, and the contract history with feedback both ways on request
corpus
30,042 full profiles, 71,351 indexed, 153 countries, refreshed daily (read 2026-09-13)
history
every row stamped fetched_at; changedSince returns what moved, with the diff
live
liveSearch for Upwork's current order; fullProfiles for a profile read now with every contract
price
$4 / $5 / $20 per 1,000 rows, no start fee, nothing for an empty run

It is an HTTP API too: one call to api.apify.com/v2/acts/moxlade~upwork-freelancers/run-sync-get-dataset-items with a JSON input returns the rows as JSON or CSV. The export guide has the request, and getmoxlade/upwork-freelancers-examples has it as a script in Python, JavaScript and curl. How this compares with the other Upwork scrapers on Apify is measured, with the harness public: the comparison.

The difference that matters

official Upwork APImoxlade/upwork-freelancers
to startapply for a key; reviewedrun it
what you can holdresponses for up to 24 hoursyour exported rows; the census is ours to keep and re-read
freelancer searcha public-profile search under a permission scopefilters on 65 columns at your thresholds
what a profile carriesthe profile as Upwork returns it to your scopeexact earnings where exposed, hours, jobs, hire-again, contracts with feedback both ways, education, employment, languages, certificates
timeyour requests, 300 a minute per IP25 stored rows in 0.4–1.9 s; a live read when you ask
whose accountyours, with its scopesnobody's — built from public profiles, anonymously
The official column is from the documentation as read on 2026-09-13; the right column from our table and our release runs.
use it

No key to apply for: run the actor from the store or call it over the Apify API with your Apify token.

moxlade/upwork-freelancers on Apify
$4.00 per 1,000 stored rows · $5.00 per 1,000 live search rows · $20.00 per 1,000 full profiles · no start fee, a zero-row run is free

Questions

Is there a free Upwork API for freelancer data?
The official API has no listed price on the documentation page we read; access is by reviewed key with a daily request limit. Our actor bills per delivered row ($4 per 1,000 stored rows) with no fee for the run itself; the Apify account it runs on has a free tier.
Does the official API let me search freelancers by Job Success Score?
The reference lists a public-profile search query and a talent-profile query with their permission scopes; the search record's listed fields are id, title, description, short name, ciphertext, portrait and similar. Filtering by JSS, hours or earnings at your own threshold is what the census route is for.
Can I keep the data I get from the official API?
Its documentation says caching is not allowed for more than 24 hours under the Terms of Service. Rows you export from our actor are yours to keep; the census itself stays with us.
Is the alternative scraping?
The census is built by reading public Upwork profiles with anonymous sessions and keeping what was read, day after day. A search against it is a table read, not a scrape; a live search or a full-profile read asks Upwork at run time. Nothing goes through your account.