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-13The 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, andtalentProfile(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;changedSincereturns what moved, with the diff - live
liveSearchfor Upwork's current order;fullProfilesfor 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 API | moxlade/upwork-freelancers | |
|---|---|---|
| to start | apply for a key; reviewed | run it |
| what you can hold | responses for up to 24 hours | your exported rows; the census is ours to keep and re-read |
| freelancer search | a public-profile search under a permission scope | filters on 65 columns at your thresholds |
| what a profile carries | the profile as Upwork returns it to your scope | exact earnings where exposed, hours, jobs, hire-again, contracts with feedback both ways, education, employment, languages, certificates |
| time | your requests, 300 a minute per IP | 25 stored rows in 0.4–1.9 s; a live read when you ask |
| whose account | yours, with its scopes | nobody's — built from public profiles, anonymously |
No key to apply for: run the actor from the store or call it over the Apify API with your Apify token.
$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 freeQuestions
- 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.