# Upwork Jobs Scraper (`curious_coder/upwork-jobs-scraper`) Actor

$0.5 per 1k jobs. Search and scrape Upwork jobs by URL or filters.

- **URL**: https://apify.com/curious\_coder/upwork-jobs-scraper.md
- **Developed by:** [Curious Coder](https://apify.com/curious_coder) (community)
- **Categories:** Jobs, Automation
- **Stats:** 20 total users, 19 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Upwork Job Scraper

Collect job listings from [Upwork](https://www.upwork.com) search results — no login, no manual copy‑pasting. Give it an Upwork search URL or pick a few filters, and the scraper returns clean, structured job data ready to export as **JSON, CSV, or Excel**.

Great for freelancers tracking new opportunities, agencies building lead lists, and analysts researching the freelance market.

### What you can do

- 🔎 Scrape jobs from **any Upwork search** — just paste the search URL from your browser.
- 🎛️ Or build a search right here using **simple filters** (keyword, budget, experience level, and more).
- 📄 Get the full **job details**: title, description, budget, required skills, experience level, and post date.
- 🔗 Get a **direct link** to every job.
- 📊 Export to **JSON, CSV, Excel**, or push the data to your own apps.
- 🔁 Run it **on a schedule** to catch new jobs automatically.

### How to use it

1. Click **Try for free**.
2. Either:
   - paste one or more **Upwork search URLs** into *Search URLs*, **or**
   - type a **keyword** and choose any **filters** you want.
3. Set **Max jobs** (how many results to collect).
4. Click **Start** and download your results when the run finishes.

#### Getting a search URL (easiest method)

1. Go to [upwork.com/nx/search/jobs](https://www.upwork.com/nx/search/jobs/) and search as you normally would.
2. Apply any filters you like (job type, budget, experience level, client location…).
3. Copy the full address from your browser's address bar and paste it into **Search URLs**.

Every filter you set on Upwork is kept in that URL, so the scraper returns exactly what you see on the site.

### Input

You can use **search URLs**, **filters**, or both. Filters are only needed if you don't provide a URL.

| Field | Description |
| --- | --- |
| **Search URLs** | One or more Upwork job‑search URLs copied from your browser. |
| **Search keyword** | Free‑text keyword (e.g. `react native`, `logo design`). |
| **Sort by** | Most recent or most relevant. |
| **Job type** | Hourly, fixed price, or weekly retainer. |
| **Experience level** | Entry level, intermediate, or expert. |
| **Hourly rate range** | Client's hourly budget, e.g. `10-50` (or `20-` for $20+). |
| **Fixed‑price budget** | Budget brackets, e.g. under $100 up to $5,000+. |
| **Client hires** | Filter by how many people the client has hired before. |
| **Client location(s)** | Regions or countries, e.g. `Americas`, `Oceania`. |
| **Project duration** | Less than a month up to 6+ months. |
| **Workload** | As needed, part time, or full time. |
| **Contract‑to‑hire only** | Only show contract‑to‑hire roles. |
| **Payment‑verified clients only** | Only show jobs from payment‑verified clients. |
| **Max jobs** | How many jobs to collect (0 = as many as available). |

#### Example input

```json
{
  "startUrls": [
    "https://www.upwork.com/nx/search/jobs/?q=full%20stack&sort=recency&t=0,1&contractor_tier=2,3"
  ],
  "maxItems": 100
}
```

Or with filters instead of a URL:

```json
{
  "searchQuery": "react native",
  "jobType": ["1"],
  "experienceLevel": ["3"],
  "fixedBudget": ["500-999", "1000-4999"],
  "sort": "recency",
  "maxItems": 50
}
```

### Output

Each job is saved as one record. Example:

```json
{
  "id": "2070162917228783082",
  "url": "https://www.upwork.com/jobs/~022070162917228783082",
  "title": "React TypeScript Developer / Full Stack Web App",
  "description": "We're looking for an experienced developer to build…",
  "jobType": "FIXED",
  "contractorTier": "ExpertLevel",
  "hourly": null,
  "fixedPrice": { "amount": "1360.0", "currency": "USD", "duration": "Less than 1 month" },
  "skills": ["React", "TypeScript", "Node.js", "Web Development"],
  "publishTime": "2026-06-25T15:14:18.014Z",
  "createTime": "2026-06-25T15:11:16.284Z",
  "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=full%20stack&sort=recency",
  "scrapedAt": "2026-06-25T15:33:35.349Z"
}
```

| Field | Description |
| --- | --- |
| `title` | Job title |
| `url` | Direct link to the job on Upwork |
| `description` | Full job description |
| `jobType` | `HOURLY`, `FIXED`, or weekly retainer |
| `contractorTier` | Experience level required (Entry / Intermediate / Expert) |
| `hourly` | Hourly budget range, engagement type, and duration (for hourly jobs) |
| `fixedPrice` | Amount, currency, and duration (for fixed‑price jobs) |
| `skills` | Skills requested for the job |
| `publishTime` / `createTime` | When the job was posted |
| `searchUrl` | The search this job came from |
| `scrapedAt` | When the record was collected |

### Tips

- **Get more results per keyword** by sorting by *Most recent* and running on a schedule, so you keep catching newly posted jobs.
- **Combine searches** by adding several URLs at once — all results land in the same dataset.
- **Export anywhere** — download as Excel/CSV/JSON from the run, or connect the dataset to Make, Zapier, Google Sheets, and more.

### FAQ

**Do I need an Upwork account?** No. The scraper reads publicly visible job listings.

**Will it return every matching job?** It collects up to **Max jobs**, within the number of results Upwork makes available for a search. Narrow your filters to focus on the most relevant jobs.

**Is scraping Upwork allowed?** Only collect publicly available data and use it responsibly, in line with Upwork's terms and applicable laws.

# Actor input Schema

## `startUrls` (type: `array`):

Full Upwork job-search URLs copied from the browser address bar (e.g. https://www.upwork.com/nx/search/jobs/?q=full%20stack\&sort=recency\&t=0,1). All on-site filters in the URL are honored.

## `searchQuery` (type: `string`):

Free-text keyword to search jobs for (used when no Search URL is given).

## `sort` (type: `string`):

Result ordering.

## `jobType` (type: `array`):

Hourly and/or fixed-price jobs.

## `experienceLevel` (type: `array`):

Freelancer experience level required by the client.

## `hourlyRate` (type: `string`):

Client hourly budget range, formatted as 'min-max' (e.g. '10-50', or '20-' for 20+). Hourly jobs only.

## `fixedBudget` (type: `array`):

Fixed-price budget buckets.

## `clientHires` (type: `array`):

Number of people the client has previously hired.

## `location` (type: `array`):

Client locations/regions (e.g. 'Americas', 'Oceania', or a country name exactly as Upwork uses it).

## `projectDuration` (type: `array`):

Expected project length.

## `workload` (type: `array`):

Hours-per-week commitment.

## `contractToHire` (type: `boolean`):

Only return contract-to-hire jobs.

## `paymentVerified` (type: `boolean`):

Only return jobs from payment-verified clients.

## `maxItems` (type: `integer`):

Maximum number of jobs to collect across all searches. Set to 0 to collect as many as Upwork makes available.

## `filtersJson` (type: `object`):

Optional. Add any additional Upwork filters as key/value pairs, e.g. { "category2\_uid": \["531770282584862721"] }. Most users can leave this empty.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.upwork.com/nx/search/jobs/?q=react&contractor_tier=2,3"
  ],
  "sort": "recency",
  "jobType": [],
  "experienceLevel": [],
  "fixedBudget": [],
  "clientHires": [],
  "location": [],
  "projectDuration": [],
  "workload": [],
  "contractToHire": false,
  "paymentVerified": false,
  "maxItems": 100
}
```

# Actor output Schema

## `jobs` (type: `string`):

Every scraped job listing (title, description, budget, skills, experience level, timestamps and job URL) as one item per job in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://www.upwork.com/nx/search/jobs/?q=full%20stack&sort=recency&t=0,1"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("curious_coder/upwork-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": ["https://www.upwork.com/nx/search/jobs/?q=full%20stack&sort=recency&t=0,1"] }

# Run the Actor and wait for it to finish
run = client.actor("curious_coder/upwork-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.upwork.com/nx/search/jobs/?q=full%20stack&sort=recency&t=0,1"
  ]
}' |
apify call curious_coder/upwork-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=curious_coder/upwork-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/9aA4gxGsECHKVoGLK/builds/I1NkqKGnYJ89eOkTx/openapi.json
