# PeoplePerHour Jobs Scraper: Freelance Projects | $1/1K (`one_dollar_store/peopleperhour-jobs-scraper`) Actor

Open PeoplePerHour projects: full brief, budget, level, category, proposals, flags and client name and country. Filter by keyword, category, budget and date. No login. $1 per 1,000 results, platform usage included.

- **URL**: https://apify.com/one_dollar_store/peopleperhour-jobs-scraper.md
- **Developed by:** [One Dollar Store](https://apify.com/one_dollar_store) (community)
- **Categories:** Jobs
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## PeoplePerHour Jobs Scraper: open freelance projects with budget, level and client country

**$1 per 1,000 projects. Platform usage included. No rental, no minimum.**

PeoplePerHour Jobs Scraper collects the open freelance projects listed on peopleperhour.com. Search by keyword, category or sub category, and narrow the list by experience level, fixed price or hourly, remote or on-site, budget, proposals so far, posting date and client country. Each row is one project with its full brief, budget in the client's currency and in US dollars, level, category, labels, proposal counts and the client's name, city and country.

[Open it in Apify Console](https://console.apify.com/actors/GEG5LTCOfFfrZowBR/input)

### How much does PeoplePerHour Jobs Scraper cost?

| Projects | This actor |
|---|---|
| 100 | $0.10 |
| 620 (every open project on 31 October 2026) | $0.62 |
| 1,000 | $1.00 |
| 10,000 | $10.00 |

Plus $0.001 per run. One flat price, platform usage included, so there is no separate compute or proxy bill. A daily run that collects the 100 newest projects in your categories costs about $0.10, or about $3 a month. PeoplePerHour lists roughly 600 open projects at a time, so one run never costs more than about a dollar.

### Why use it

- **The whole brief in every row.** The full project text, not a cut-off snippet, with budget, currency, experience level, category, sub category, duration and the labels Urgent, Featured, Opportunity, Pre-funded and NDA.
- **Filters that save money.** Keyword, category, sub category, experience level, budget type, work location, project label and sort order are applied by PeoplePerHour before the actor reads a page. Budget range, proposals so far, posting date, client country and verified clients are applied by the actor, and rows that do not match are never billed.
- **Client facts for lead lists.** Client name as shown on the project, city, country, member since date and verification flag, so you can sort by region or by how new the client is.
- **Fast.** All 620 open projects were read in 46 seconds in our test, 20 projects per request.
- **No login, no key, no proxy.** It reads what a logged out visitor sees.

### How to use PeoplePerHour Jobs Scraper

1. Open the actor, pick a category or type a keyword, press **Start**.
2. Or paste this input:

```json
{
  "searchKeywords": ["wordpress", "web design"],
  "experience": ["expert"],
  "pricing": "fixed_price",
  "minBudgetUsd": 200,
  "postedWithinDays": "7",
  "maxItems": 200
}
```

3. Download the results as JSON, CSV or Excel, or read them through the API.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/one_dollar_store~peopleperhour-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"categories": ["technology-programming"], "maxItems": 50}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("one_dollar_store/peopleperhour-jobs-scraper").call(
    run_input={"categories": ["technology-programming"], "maxItems": 50}
)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["postedAt"], job["budget"], job["currency"], job["title"], job["url"])
```

### Use it from an AI assistant

Claude, ChatGPT, Cursor and other assistants can call this actor through Apify's MCP server. Add it with this server address:

```
https://mcp.apify.com?tools=one_dollar_store/peopleperhour-jobs-scraper
```

Then ask, for example: "List the 20 newest expert level WordPress projects on PeoplePerHour with a budget over $200 and fewer than 15 proposals."

### Switching from another PeoplePerHour actor

Most PeoplePerHour actors take keywords, category slugs or listing links, a sort order and a result limit. Here they are `searchKeywords`, `categories` and `subcategories` (pick lists), `startUrls`, `sort` and `maxItems`. The core fields are `projectId`, `title`, `description`, `budget`, `currency`, `budgetUsd`, `budgetType`, `experienceLevel`, `locationType`, `category`, `subcategory`, `postedAt`, `expiresAt`, `proposalCount`, `isUrgent`, `isFeatured`, `isOpportunity`, `isPreFunded`, `clientName`, `clientCity`, `clientCountry` and `url`. The experience level (entry, intermediate, expert) comes from PeoplePerHour's budget bracket.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchKeywords` | list of text | none | Words to look for in project titles and briefs, up to 25. Each is searched on its own and the results are merged without repeats. Empty means no keyword. |
| `categories` | pick list | none | One or more of the 10 categories, such as `technology-programming` or `design`. Empty means all. |
| `subcategories` | pick list | none | One or more of the 129 sub categories, such as `web-design` or `seo`. Each belongs to one category. |
| `startUrls` | list of links | none | PeoplePerHour listing pages to read instead of the fields above. Filters in the link are kept; the other site filters are ignored for links. Links to single projects are skipped. |
| `experience` | pick list | all | `entry`, `intermediate` and `expert`, one or more. |
| `pricing` | choice | `any` | `fixed_price`, `hourly` or both. |
| `location` | choice | `any` | `remote` or `onsite`. |
| `projectType` | choice | `any` | Only projects with the label `urgent`, `noProposals`, `preFunded`, `featured` or `opportunity`. |
| `sort` | choice | `default` | Newest first, or best match when a keyword is given. Also `popularity`, `ending` and `budget`. |
| `minBudgetUsd`, `maxBudgetUsd` | number | none | Budget range in US dollars. For hourly projects the budget is the hourly rate. |
| `maxProposals` | number | none | Skip projects that already have more proposals than this. `0` finds projects nobody has answered. |
| `postedWithinDays` | choice | `any` | `1`, `3`, `7`, `14` or `30` days. |
| `clientCountries` | list of text | none | Two letter codes of the client country, such as `GB`, `US`, `AU`. |
| `verifiedClientsOnly` | true or false | false | Keep only projects from verified clients. |
| `includeClientDetails` | true or false | true | Adds the client name, member number and profile link. Turn off to leave them out. |
| `maxItems` | number | 100 | Total projects for the run. Minimum 10, maximum 10,000. |
| `maxItemsPerSource` | number | none | Cap for each keyword and category combination. |

Example with several categories and keywords:

```json
{
  "searchKeywords": ["shopify", "woocommerce"],
  "categories": ["technology-programming", "digital-marketing"],
  "location": "remote",
  "clientCountries": ["GB", "US"],
  "maxProposals": 20,
  "maxItems": 300
}
```

### What data does PeoplePerHour Jobs Scraper return?

Each row is one open project. Fields PeoplePerHour does not show for a project are left out of that row.

| Field | Meaning |
|---|---|
| `projectId`, `url`, `title` | PeoplePerHour's number for the project, the link to it and its title. |
| `description` | The full brief as plain text, line breaks kept. |
| `category`, `categoryId`, `categorySlug` | Main category. The slug can be used as an input value. |
| `subcategory`, `subcategoryId`, `subcategorySlug` | Sub category. The slug can be used as an input value. |
| `budgetType` | `fixed` for a fixed price project, `hourly` for an hourly rate. |
| `budget`, `currency` | Budget in the currency the client chose (GBP, USD or EUR). For hourly projects this is the hourly rate. |
| `budgetUsd` | The budget as PeoplePerHour converted it to US dollars when the page was read. |
| `experienceLevel` | `entry`, `intermediate` or `expert`, from PeoplePerHour's budget bracket. |
| `locationType` | `remote`, `remote_country` (remote, but only from one country) or `onsite`. |
| `whereCanBid`, `biddersCountry` | `ALL`, or the country code and name when bids are limited to one country. |
| `onsiteCity`, `onsiteRegion`, `onsiteCountry`, `onsiteCountryCode` | Workplace of on-site projects. |
| `duration` | Expected length of the work, when the client gave one. |
| `status` | `open` for every row. |
| `isUrgent`, `isFeatured`, `isOpportunity`, `isPreFunded`, `hasNda` | The labels PeoplePerHour puts on a project. `isPreFunded` means the budget is already in escrow. |
| `postedAt`, `expiresAt` | When the project was posted and when it closes for proposals. ISO date and time without a time zone, because PeoplePerHour gives none. |
| `proposalCount`, `unreadProposalCount` | Proposals the project had when read, and how many of them the client had not opened. |
| `clientId`, `clientName`, `clientProfileUrl` | The client as PeoplePerHour shows them on the project, often a first name and a last initial. Left out when `includeClientDetails` is off. |
| `clientCity`, `clientCountry`, `clientCountryCode` | Where the client says they are. |
| `clientMemberSince`, `clientVerified` | Date the client joined and whether PeoplePerHour marks them as verified. |
| `searchKeyword` | The keyword that found the project. Empty when no keyword was used. |
| `listingUrl`, `listingPage`, `listingPosition` | The listing page the project came from and its place on that page. |
| `scrapedAt` | When the page was read, ISO 8601, UTC. |

### Sample results

Real rows from the volume test on 31 October 2026, shortened to the main fields.

```json
[
  {"projectId": "4529130", "title": "Claude designed app needs moving to Azure for scale.", "category": "Technology & Programming", "subcategory": "Programming & Coding", "budgetType": "fixed", "budget": 155, "currency": "GBP", "budgetUsd": 207.68, "experienceLevel": "entry", "locationType": "remote", "isOpportunity": true, "postedAt": "2026-10-31T12:10:13", "proposalCount": 44, "clientName": "Shaun J.", "clientCity": "Brighton", "clientCountryCode": "GB", "clientVerified": false, "url": "https://www.peopleperhour.com/freelance-jobs/technology-programming/programming-coding/claude-designed-app-needs-moving-to-azure-for-scale-4529130"},
  {"projectId": "4529123", "title": "UK/EPO Patent Disclosure Advice,Google Play Closed Testing (£50)", "category": "Business", "subcategory": "Legal Services", "budgetType": "fixed", "budget": 51, "currency": "GBP", "budgetUsd": 68.33, "experienceLevel": "entry", "locationType": "remote", "isOpportunity": false, "postedAt": "2026-10-31T09:41:06", "proposalCount": 4, "clientName": "Sb C.", "clientCity": "High Wycombe", "clientCountryCode": "GB", "clientVerified": false, "url": "https://www.peopleperhour.com/freelance-jobs/business/legal-services/uk-epo-patent-disclosure-advice-google-play-closed-testing-4529123"},
  {"projectId": "4529112", "title": "WordPress Webpages Revisions", "category": "Design", "subcategory": "Web Design", "budgetType": "fixed", "budget": 30, "currency": "USD", "budgetUsd": 30, "experienceLevel": "entry", "locationType": "remote", "isOpportunity": false, "postedAt": "2026-10-31T08:02:39", "proposalCount": 38, "clientName": "Timothy O.", "clientCity": "London", "clientCountryCode": "GB", "clientVerified": false, "url": "https://www.peopleperhour.com/freelance-jobs/design/web-design/wordpress-webpages-revisions-4529112"}
]
```

### Limits

- PeoplePerHour lists about 620 open projects at a time (31 October 2026). A run returns what is open at that moment, so `maxItems` above that number changes nothing. For a longer history, schedule the actor daily and keep the `projectId` values you already have.
- The public listing shows a category and a sub category for each project, not a list of skills. Use the keyword filter to find a skill.
- The keyword search runs on PeoplePerHour. It matches words in the title and brief. Keywords with symbols, such as `c++`, find nothing there.
- Posting times carry no time zone. The `postedWithinDays` cut off treats them as UTC, so it can be an hour out.
- `budgetUsd` is PeoplePerHour's own conversion on the day of the read, so the same project can show a slightly different value in a later run.
- Client names are what PeoplePerHour shows publicly on the project, often a first name and a last initial. There are no email addresses or phone numbers: PeoplePerHour does not show them to visitors. Turn `includeClientDetails` off if you do not want the name, member number and profile link.
- Closed, private and draft projects are not listed publicly, so they are not included.
- With a keyword and no sort, PeoplePerHour orders by best match. Without a keyword the default is newest first.
- When you paste listing links in `startUrls`, only the filters inside the link are used. Keywords, categories and the other site filters in the form are ignored, but the local filters (budget, proposals, date, client country) still apply.
- The actor reads one page a second, 20 projects each, with an honest User-Agent and no proxy. If PeoplePerHour refuses three requests in a row or shows a verification page, the run stops and says so in its status line. A run that cannot read a single page ends as failed with the reason. You are charged only for the rows delivered.

### FAQ

**How much does it cost to scrape 10,000 PeoplePerHour projects?**
$10, plus $0.001 for each run. In practice PeoplePerHour lists about 600 open projects at a time, so one full read costs under a dollar. Reaching 10,000 means collecting over several weeks.

**Do I pay for compute or proxy on top?**
No. Platform usage is included in the $1 per 1,000 price. The actor reads PeoplePerHour directly and uses no proxy.

**Where does the data come from?**
From the public listing pages of peopleperhour.com, which anyone can open without logging in. The actor reads the project data that each listing page carries. It needs no key and no login.

**How do I get only new projects every day?**
Schedule a daily run with `postedWithinDays` set to `1` and keep the `projectId` values you already have. Add `maxProposals` to find projects that few freelancers have answered.

**Why did I get fewer rows than I asked for?**
There were not that many matching open projects. Keywords and filters narrow the list a lot: a keyword such as `wordpress` matched about 30 open projects on 31 October 2026. Widen the keyword or remove a filter. The run still ends without an error and the status line says how many rows were delivered.

**Is it legal?**
The actor collects only public data that PeoplePerHour shows to any visitor. You are responsible for how you use it: follow the data protection laws that apply to you, such as GDPR, especially when you store or process names of people, and do not use the data to send unwanted messages. PeoplePerHour's terms of website use say that visitors may not use automated software to crawl or spider the site, may not harvest or scrape its content, and may not use its materials for commercial purposes without a licence. Its robots.txt asks automated clients not to fetch addresses that carry a query string other than the page number, and the filter and sort links work that way. This actor reads only public listing pages as a logged out visitor, one request a second, and stops at any verification page. You decide for yourself whether and how to use the data.

**Is this an official PeoplePerHour product?**
No. It is an independent tool and is not affiliated with or endorsed by PeoplePerHour.

### Feedback and support

Found a problem or want a field added? Open an issue on the Issues tab of this actor and it gets read. If the actor saved you time, an honest rating on the Reviews tab helps other people find it.

**Do I need an Apify account?**
Yes. Actors run from an Apify account, and a free account is enough to start: it includes $5 of platform usage every month. You can [sign up here](https://www.apify.com?fpr=ymnoit). This is a referral link and it costs you nothing.

**Is there a limit on the free plan?**
Yes. A run started from a free plan account delivers the first 10 results, then ends with a message and a link to the plans. Any paid plan returns everything you ask for, up to your own limit. The price per result is the same on every plan.

### More from The One Dollar Store

Every actor here costs $1 per 1,000 results, platform usage included. See the whole store: https://apify.com/one_dollar_store

**Jobs**

- [Foundit Jobs Scraper](https://apify.com/one_dollar_store/foundit-jobs-search-scraper): Indian jobs with salary and experience filters.
- [Naukri Jobs Scraper](https://apify.com/one_dollar_store/naukri-job-listings-scraper): Naukri.com jobs by keyword, city and experience.
- [Greenhouse Jobs Scraper](https://apify.com/one_dollar_store/greenhouse-jobs-scraper): Open roles from Greenhouse company boards.
- [Lever Jobs Scraper](https://apify.com/one_dollar_store/lever-jobs-scraper): Open roles from Lever company boards.
- [SmartRecruiters Jobs Scraper](https://apify.com/one_dollar_store/smartrecruiters-jobs-scraper): Open roles from SmartRecruiters companies.
- [Remote Jobs Scraper](https://apify.com/one_dollar_store/remote-jobs-scraper): Remote roles from two public job boards.
- [Hirist Jobs Scraper](https://apify.com/one_dollar_store/hirist-jobs-scraper): Tech job listings from hirist.tech.
- [Gupy Jobs Scraper](https://apify.com/one_dollar_store/gupy-jobs-scraper): Job vacancies posted on Gupy in Brazil.
- [Shine Jobs Scraper](https://apify.com/one_dollar_store/shine-jobs-search-scraper): Job listings from shine.com in India.
- [Internshala Scraper](https://apify.com/one_dollar_store/internshala-internships-scraper): Internships and fresher jobs from internshala.com.

### Changelog

- 1 November 2026: clearer description and headings, field details for AI tools. Price and output unchanged.
- November 2026: first release.

# Actor input Schema

## `searchKeywords` (type: `array`):

Words to look for in project titles and briefs, for example wordpress, web design or logo. Each keyword is searched on its own and the results are merged without duplicates. Leave empty to read all open projects.

## `categories` (type: `array`):

Only projects in these categories. Leave empty for every category.

## `subcategories` (type: `array`):

Only projects in these sub categories (each belongs to one category). Leave empty for all.

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

PeoplePerHour listing pages to read instead of the fields above, for example https://www.peopleperhour.com/freelance-jobs/design. Filters in the link (experience, pricing, location, sort) are kept. Links to single projects are skipped.

## `experience` (type: `array`):

Only projects asking for these levels. Leave empty for all levels.

## `pricing` (type: `string`):

Fixed price projects, hourly projects or both.

## `location` (type: `string`):

Remote projects only, on-site projects only, or both.

## `projectType` (type: `string`):

Only projects that carry this label on PeoplePerHour.

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

Order of the results. Default is newest first, or best match when you give a keyword.

## `minBudgetUsd` (type: `integer`):

Skip projects below this budget. PeoplePerHour converts every budget to US dollars; for hourly projects this is the hourly rate.

## `maxBudgetUsd` (type: `integer`):

Skip projects above this budget, in US dollars.

## `maxProposals` (type: `integer`):

Skip projects that already have more proposals than this. Use 0 for projects nobody has answered yet.

## `postedWithinDays` (type: `string`):

Only projects posted in the last days. PeoplePerHour gives posting times without a time zone, so the cut off can be an hour out.

## `clientCountries` (type: `array`):

Two letter country codes of the client, for example GB, US, AU. Leave empty for all countries.

## `verifiedClientsOnly` (type: `boolean`):

Keep only projects whose client is verified on PeoplePerHour.

## `includeClientDetails` (type: `boolean`):

Adds the client's name, member number and profile link to each row. These are the details PeoplePerHour shows publicly on the project page. Turn off to leave them out and keep only the client's city, country and verification.

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

Stop after this many projects in total. PeoplePerHour lists roughly 600 open projects at a time, so a run with no filters returns about that many at most. Minimum 10.

## `maxItemsPerSource` (type: `integer`):

Optional cap for each keyword and category combination, so one busy keyword does not use up the whole run.

## Actor input object example

```json
{
  "categories": [
    "technology-programming"
  ],
  "pricing": "any",
  "location": "any",
  "projectType": "any",
  "sort": "default",
  "postedWithinDays": "any",
  "verifiedClientsOnly": false,
  "includeClientDetails": true,
  "maxItems": 50
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "categories": [
        "technology-programming"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("one_dollar_store/peopleperhour-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 = {
    "categories": ["technology-programming"],
    "maxItems": 50,
}

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

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

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

```

## CLI example

```bash
echo '{
  "categories": [
    "technology-programming"
  ],
  "maxItems": 50
}' |
apify call one_dollar_store/peopleperhour-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,one_dollar_store/peopleperhour-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/GEG5LTCOfFfrZowBR/builds/Y51Vmg3t2iMz0YGgD/openapi.json
