# Upwork Jobs Scraper: Pay, Clients and Job Alerts

> Upwork scraper: get public job posts by search phrase, search link or job ID. Pay, skills, applicants and client spend, with new job alerts. No login.

URL: https://cliqtomedia.com/actors/upwork-jobs-scraper/

Category: Jobs & hiring · Status: live on Apify Store · Apify page: https://apify.com/cliqtomedia/upwork-jobs-scraper?fpr=cliqto

Get public Upwork job posts without an account or cookies. Use a search phrase, a search link, a job link or a job ID. Each row has pay, skills, applicants and public client data.

## How to use it: 3 steps

1. **Make a free Apify account.** Apify is the cloud platform where our tools run. The free plan gives you $5 of usage every month, no credit card needed. You pay Apify, not us.
2. **Paste your input and press Start.** No code needed: you fill in a form (the input). It already has a working example. For example: `web scraping` in Search phrases. Each start is one run.
3. **Download the results.** When the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.

## What it does

Use this Upwork jobs scraper to get public Upwork job posts by search phrase, search link, job link or job ID. Find clients, track freelance demand or get new job alerts. Each row has pay, skills, applicants and public client data such as country, spend and rating. No Upwork account or cookies needed.



### Good for

- Find new clients and leads for a freelance team or agency.
- Track demand, pay and skills in a job category.
- Get an alert when a new job matches your search.
- Feed job rows to a sheet, database, Slack, Notion or an AI agent.

## Price

Pay per event. Apify bills you, not us.

| What you pay for | Price | When |
|---|---|---|
| Start fee | $0.001 | Charged once per run. This tool uses 1 GB of memory or less by default; more memory costs more. |
| Source request | $0.0001 | One public source request started, including empty results and jobs that do not match filters. Redirects and retries are included. |
| Saved job | $0.0009 (from $0.00063 on paid Apify plans) | One job saved in the dataset. |

- One result: about $0.0019.
- 1,000 results: about $0.90.
- Every day 100 results, for 30 days: about $2.73 a month.

Free to try: the Apify free plan gives you $5 of usage every month, no credit card needed.

Prices checked on 8 November 2026. Current price: https://apify.com/cliqtomedia/upwork-jobs-scraper?fpr=cliqto

## Questions

### Do I need an Upwork account or cookies?

No. The Actor reads only what Upwork shows to visitors. Do not give it your login.

### Why is clientRating null?

The client has no public reviews yet. Null means unknown or hidden. It is not the same as 0.

### Can this Actor apply for jobs or contact clients?

No. It only reads public job posts.

### Can I scrape Upwork jobs by a search link?

Yes. Run your search on Upwork, copy the link and paste it in `startUrls`. Filters in the link are used.

### How do I get only new jobs?

Set `onlyNew: true` and run the Actor on an Apify Schedule. The first run saves all matches up to `maxItems` as a starting point. Later runs save only jobs not saved before.

### Why do I pay for source requests when no job is saved?

The Actor must read the source to find out if a job matches. So each source request is charged, even if your filters remove all jobs. Make filters part of the search when you can, for example `jobType` or `experienceLevel`.

### How fresh is the data?

Each row is read during the run, and `fetchedAt` shows the time. Rows are not updated later. Run again or use a schedule for fresh data.

### Is this an official Upwork product?

No. This Actor is not affiliated with or endorsed by Upwork.

## Data fields

- `jobId` (string): Upwork job ID.
- `id` (string): The same ID as jobId, for imports.
- `ciphertext` (string): Upwork ID used in the job link.
- `title` (string): Job title, with contact details removed.
- `description` (string): Full public job text, with email addresses and phone-like numbers removed.
- `budget` (number): Fixed-price budget. Null for hourly jobs or an undisclosed budget.
- `budgetCurrency` (string): Currency code of the fixed budget.
- `hourlyRange` (object): Known minimum and maximum hourly rates. Null limits mean undisclosed.
- `hourlyBudgetMin` (number): Known minimum hourly rate.
- `hourlyBudgetMax` (number): Known maximum hourly rate.
- `weeklyRetainerBudget` (number): Weekly retainer budget, when public.
- `jobType` (string): hourly, fixed or weekly_retainer.
- `experienceLevel` (string): entry, intermediate or expert.
- `skills` (array): Public skill names.
- `skillIds` (array): Public skill IDs.
- `duration` (string): Project duration label.
- `durationWeeks` (number): Project duration in weeks.
- `workload` (string): Weekly work requirement.
- `postedAt` (string): Publication time reported by Upwork.
- `absoluteDate` (string): The same publication time as postedAt.
- `createdAt` (string): Time the job was created.
- `renewedAt` (string): Source renewal or sourcing time, if given.
- `clientCountry` (string): Client country name. Source country codes are converted to country names. Null when hidden.
- `clientCountryCode` (string): Two-letter ISO country code from the public client country name. Null when the name cannot be matched.
- `clientCity` (string): Public client city, when visible.
- `clientTimezone` (string): Public client timezone label.
- `clientPaymentVerified` (boolean): Whether the public page shows a verified payment method.
- `paymentVerified` (boolean): The same value as clientPaymentVerified.
- `clientTotalSpent` (number): Public lifetime client spend. A hidden amount stays null.
- `clientSpentCurrency` (string): Currency of the public client spend.
- `clientRating` (number): Public client rating. Null when the client has no reviews.
- `clientReviewCount` (number): Public review count.
- `clientTotalHires` (number): Public total client assignments.
- `clientActiveHires` (number): Public active assignments.
- `clientTotalHours` (number): Public hours billed.
- `clientMemberSince` (string): Public client account creation date.
- `clientIndustry` (string): Public client industry. Null when empty.
- `clientCompanySize` (number): Company size group reported by Upwork. The group code is not a staff count.
- `clientHireRatePercent` (number): Null when this value is hidden from visitors.
- `clientAvgHourlyRate` (number): Null when this value is hidden from visitors.

## Input settings

- `queries` (array): Search each phrase. Results from all searches share the result limit. Leave blank when you use URLs or job IDs.
- `startUrls` (array): Public Upwork search or job links. Search filters in a link take the place of the same input filters.
- `jobIds` (array): Read public details for these job IDs. Use the numeric ID or the ID that starts with ~02.
- `maxItems` (integer): Stop after saving this many matching jobs across all inputs. The source may have fewer jobs. Pages read before this limit still count as source work.
- `includeDetails` (boolean): Include the public client panel, job activity and requirements. A job that is visible only to members keeps its search fields.
- `mode` (string): Search finds jobs. Details reads job links or IDs. Monitor keeps a history and returns new or changed jobs.
- `jobType` (array): Keep hourly, fixed-price or weekly retainer jobs.
- `experienceLevel` (array): Keep the selected experience levels.
- `categories` (array): Upwork category IDs. Choose a category by name. Leave blank for all categories.
- `minBudget` (number): Keep jobs with a known fixed budget at or above this amount.
- `maxBudget` (number): Keep jobs with a known fixed budget at or below this amount.
- `minHourlyRate` (number): Keep jobs whose known minimum hourly rate is at or above this amount.
- `maxHourlyRate` (number): Keep jobs whose known maximum hourly rate is at or below this amount.
- `workload` (array): Filter by the weekly time needed.
- `duration` (array): Filter by the source project duration group.
- `contractToHire` (boolean): Keep jobs marked as contract-to-hire. Needs public job details.
- `includeKeywords` (array): Each word or phrase must appear in the title, description or skills.
- `excludeKeywords` (array): Skip a job if any word or phrase appears in its title, description or skills.
- `requiredSkills` (array): Each skill name must be in the job skills. Match ignores letter case.
- `titleContains` (string): Keep jobs whose title contains this phrase. Match ignores letter case.
- `maxAgeMinutes` (number): Keep jobs published within this many minutes.
- `maxJobAge` (object): Alternative age filter with value and unit. Units: minutes, hours, days or weeks.
- `fromDate` (string): Keep jobs published on or after this UTC date or time. Use YYYY-MM-DD or an ISO time ending in Z.
- `toDate` (string): Keep jobs published through this UTC date or time. A date without a time includes the full day.
- `proposals` (array): Keep jobs with an exact applicant count inside these ranges. Needs public job details.

## Step by step on Apify

1. Open the Input tab. Keep `web scraping` in Search phrases, or type your own phrase (box 1).
2. Keep `10` in Maximum results for a first test (box 2). Filters are optional, see Input.
3. Click Start.
4. When the run ends, open the Output tab. Each row is one job (box 4). Check the job title, budget, client spend and applicants.

## Use cases

| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Find clients who pay well | `queries`, `minClientTotalSpent`, `paymentVerified: true` | One job per row | `title`, `clientCountry`, `clientTotalSpent`, `clientRating`, `url` | CRM or a sheet |
| Get new job alerts | `queries`, `onlyNew: true`, Apify Schedule | Only jobs not saved before | `title`, `budget`, `hourlyRange`, `postedAt`, `url` | Slack or Notion with `deliveryConnector` |
| Track market demand and pay | `queries` or `categories`, `maxItems: 1000` | One job per row | `skills`, `hourlyBudgetMin`, `hourlyBudgetMax`, `budget`, `category` | Sheet or BI tool |
| Copy a search you made on Upwork | `startUrls` with an Upwork search link | One job per row | `title`, `jobType`, `experienceLevel`, `postedAt`, `url` | Dataset API |
| Check known jobs | `jobIds` or job links in `startUrls` | One row per public job | `jobStatus`, `totalApplicants`, `hired`, `clientLastActivity`, `detailsStatus` | Your own job tracker |

## Tips

- Keep 10 in Maximum results for a first test.
- Paste a search link from Upwork in startUrls. The filters in the link are used.
- Set onlyNew to true and use an Apify Schedule to get only new jobs.

## Limits



- Only public data. There is no login, so private and invite-only jobs are not available.
- Some jobs show details only to members. In our 6,000-job test, 1,055 jobs had no public details. These rows keep the search fields and have `detailsStatus: "members_only"`.
- `clientAvgHourlyRate` and `clientHireRatePercent` are hidden from visitors, so they stay null.
- The largest tested run saved 6,000 jobs in about 20 minutes. The default timeout is 300 seconds. Raise it for runs over about 1,000 jobs.
- A big search is split by category, type and experience level to get past the source limit of about 5,000 results per search. So a big result has no single global order.
- If the source still holds back part of a search, the summary says `SOURCE_CAP` and `sourceCapPartitions` counts the affected parts.
- `skipReposts` skips only exact repeats of the cleaned title and description. Reworded reposts are saved.
- A monitor history keeps up to 100,000 jobs. Closed and then the oldest jobs are dropped first.

## Sample result

```json
{
  "jobId": "2117702916010329632",
  "title": "Social Media automated data collection (API) and Website Data Collection",
  "jobType": "hourly",
  "hourlyRange": {
    "min": 6,
    "max": 25
  },
  "budget": null,
  "experienceLevel": "intermediate",
  "skills": [
    "Data Scraping",
    "Web Scraping",
    "API Integration",
    "Social Media Marketing"
  ],
  "duration": "1 to 3 months",
  "postedAt": "2026-11-03T19:38:23.701Z",
  "clientCountry": "United States",
  "clientPaymentVerified": true,
  "clientTotalSpent": 599.1,
  "clientSpentCurrency": "USD",
  "clientRating": 5,
  "clientReviewCount": 2,
  "clientTotalHires": 5,
  "totalApplicants": 37,
  "jobStatus": "open",
  "detailsStatus": "available",
  "url": "https://www.upwork.com/jobs/~022117702916010329632",
  "fetchedAt": "2026-11-04T12:08:00.362Z"
}
```

## Use it from code

Actor ID: `cliqtomedia/upwork-jobs-scraper`

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("cliqtomedia/upwork-jobs-scraper").call(run_input={
    "queries": [
        "web scraping"
    ],
    "maxItems": 10
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

```bash
curl -X POST "https://api.apify.com/v2/acts/cliqtomedia~upwork-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["web scraping"], "maxItems": 10}'
```

```python
# pip install langchain-apify
# set APIFY_TOKEN in your environment
from langchain_apify import ApifyActorsTool

tool = ApifyActorsTool("cliqtomedia/upwork-jobs-scraper")
result = tool.invoke({"run_input": {"queries": ["web scraping"], "maxItems": 10}})
print(result)
```

run-sync waits up to 300 seconds; for longer runs start a run and use a webhook. LlamaIndex and MCP: https://cliqtomedia.com/actors/ai-agents/

## Similar tools

- [Remote Jobs Aggregator - RemoteOK, WWR & Himalayas, No login](https://cliqtomedia.com/actors/remote-jobs-aggregator/)
- [Wellfound Jobs Scraper: Startup Jobs to CSV & JSON](https://cliqtomedia.com/actors/wellfound-jobs-scraper/)
- [Google Jobs Scraper - Salary, Apply Links & Dates, No Login](https://cliqtomedia.com/actors/google-jobs-scraper/)
- [Ashby Jobs Scraper: Public Job Board Export](https://cliqtomedia.com/actors/ashby-jobs-scraper/)
- [Lever Jobs Scraper: jobs.lever.co Postings Export](https://cliqtomedia.com/actors/lever-jobs-scraper/)
- [Greenhouse Jobs Scraper & Monitor: Job Board Export](https://cliqtomedia.com/actors/greenhouse-jobs-monitor-scraper/)
