Using the Upwork API without getting blocked

Using the Upwork API without getting blocked

blackfalcondata

Building against an Upwork API rarely fails at the parsing stage. The harder part is staying in: requests work, then responses arrive empty or truncated—or return a challenge page the parser cannot handle.

Here is what our own Upwork Actor handles, what each run costs, and where the Actor stops.

Doing it yourself

The DIY route makes sense for a single snapshot, or when the data is simple enough that a failed run has no cost. The work involved is less simple. These specifics come directly from the safeguards built into our own scraper.

The front door. Upwork's protection is not deterministic. Across 3 plain requests on 2026-08-22, 1 got a page and 2 were refused with 403 behind Cloudflare, actively challenging. That inconsistency is difficult to build around: a test passes, then production volume fails.

Getting past the gate. A 403 from Upwork does not always mean refusal. It often points to a stale session cookie. Obtaining a new cookie and repeating the request can fix it; backing off will not.

Telling a challenge from a block. Upwork uses the same status for "prove you are a browser" and "go away". The body reveals which response you received. A client that ignores it wastes its retry budget on the second case.

Rate limits. Upwork rate-limits per-source rather than per-account. Exponential backoff slows the run. Without it, the run fails.

Proxies. A thousand Upwork page requests from one IP form a pattern, not ordinary traffic. Rotation makes that volume unremarkable—and becomes the largest line item on the bill.

Pagination. An Upwork pagination loop needs to tell "no more results" apart from "we stopped being served results". Both conditions can produce an empty page.

Silent breakage. Upwork redesigns rarely produce loud scraper failures. A selector breaks, a field returns empty, and the run still reports success. The first warning is often a report that looks thin.

The real cost is upkeep. The first version takes an afternoon. Keeping it functional takes an hour every few weeks, forever. Failures stay quiet: an empty report exposes the problem, not a scraper error.

These figures come from a measured run, not an estimate:

  • 25 records in 5.1 seconds
  • cost: $0.00028 — about $0.01 per 1,000 records

The shortcut

If you do not want to maintain that machinery, one call returns the same result:

```bash curl -X POST "https://api.apify.com/v2/acts/blackfalcondata~upwork-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"query": "..."}' ```

The Python equivalent:

```python from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN") run = client.actor("blackfalcondata~upwork-scraper").call(run_input={"query": "..."})

for item in client.dataset(run["defaultDatasetId"]).iterate_items(): print(item) ```

What comes back

Every row contains 55 fields, organized into several groups:

  • client — clientCountry, clientCountryCode, clientTotalSpent, clientSpentCurrency, clientPaymentVerified, clientRating, +2 more
  • salary — salaryMin, salaryMax, salaryCurrency, salaryType
  • description — description, descriptionHtml, descriptionMarkdown

What people use it for

  • Benchmarking. Pricing and salary fields allow comparisons across the entire set instead of relying on a page of results.
  • Reputation monitoring. Changes in ratings and review text over time reveal movement that one page view cannot show.
  • Geographic analysis. Location fields provide market-by-market comparisons without requiring another data source.

Limits

  • Nothing here bypasses a Upwork login. Public pages only, regardless of who writes the scraper.
  • A scraper that works today may not work in six weeks. Failure usually arrives as silence, not an exception.
  • Proxy cost rises with volume. It is also the expense people tend to omit from DIY estimates.

Questions people ask

Is scraping Upwork legal?

Reading publicly visible pages is generally treated differently from accessing data behind a login, and courts in the US have repeatedly declined to treat public scraping as unauthorised access. That is not legal advice, and a site's terms of service remain separate from the law. Anything behind a login is out of scope either way.

Why am I getting 403s when the page loads fine in my browser?

The check concerns more than the URL. On 2026-08-22, cloudflare answered a plain request to Upwork from our probe and actively challenged it; 2 of 3 attempts were refused. A browser passes because it supplies a TLS fingerprint, a cookie and a header set that a bare HTTP client lacks.

Do I need proxies?

Yes, for anything larger than a small sample. Our own input exposes `proxyConfiguration` because a single origin IP is exceptionally easy to rate-limit.

How often will it break?

Plan to touch the scraper whenever Upwork releases a redesign. You may not notice immediately: extraction fails quietly, producing empty fields instead of errors. Budget an hour every few weeks, not a fix-and-forget afternoon.

Is it cheaper to build it myself?

Only when your time is free. The measured run below cost $0.00028 for 25 records. A DIY version adds proxy spend and a recurring maintenance hour.

Try it

To avoid owning the upkeep, use the Upwork API endpoint we maintain. It already handles everything described above. New accounts receive $5 of free platform credit each month, enough to cover a real run of this size several times over.

Disclosure: we build and maintain this Actor, and the link above is an affiliate link.

Further reading


We also publish the Upwork API endpoint and what it returns on blackfalcondata.com — the request, the response, and what a run costs.

Report Page