
Global Sources Supplier Scraper
scrape.ly/store/cornerledger/globalsources-scraperLead generationE-commerce
2 monthly users

Search PeoplePerHour freelance jobs by keyword, category or link, or paste job links. Get title, full description, budget in the original currency and USD, experience level, proposal count, posting and expiry dates, location and client details. No login needed.
Export freelance jobs from PeoplePerHour in seconds: title, full description, budget in the client's currency and in US dollars, experience level, proposal count, posting and expiry dates, location and client details. Search by keyword, filter by category, pricing, experience, budget and age, or paste PeoplePerHour links. No login, no browser, and you pay only for the jobs you get.
wordpress, logo design), or paste PeoplePerHour links (job search or category pages like peopleperhour.com/freelance-jobs/technology-programming, or single job pages).Leave the keywords empty and pick a category or another filter to get every job that matches it.
| Field | What it does |
|---|---|
queries | Search keywords; each one is its own search |
startUrls | Job search / category links and single job links |
maxItems | Jobs per keyword or link (default 20, 0 = all the site lists) |
category | One of the site's 10 job categories |
projectType | all, fixed_price or hourly |
experienceLevels | Any of entry, intermediate, expert |
minBudget / maxBudget | Budget range in US dollars (hourly rate for hourly jobs) |
maxProposals | Jobs with at most this many proposals |
postedWithinDays | Only jobs posted in the last N days |
remoteOnly, urgentOnly, preFundedOnly, opportunityOnly, noProposalsOnly | The site's job filters |
includeClosedJobs | Also return in-progress, completed and expired jobs |
sortBy | newest, relevance, budget, ending, popularity |
{
"queries": ["wordpress", "shopify"],
"maxItems": 50,
"projectType": "fixed_price",
"experienceLevels": ["intermediate", "expert"],
"minBudget": 200,
"maxProposals": 10,
"postedWithinDays": 3,
"sortBy": "newest"
}
One row per job.
| Field | Description |
|---|---|
project_id, title, url | Job id, title and link |
description | Full job description |
budget, currency | Budget in the client's currency (hourly rate for hourly jobs) |
budget_converted, budget_converted_currency | Budget converted to US dollars by the site |
project_type | fixed_price or hourly |
budget_bracket, experience_level | 1 Entry, 2 Intermediate, 3 Expert |
category, category_slug, sub_category, sub_category_slug | Where the job is listed |
posted_date, expiry_date | As the site shows them (YYYY-MM-DD HH:MM:SS) |
status, is_open | open, in_progress, completed, expired... |
location_type, remote_country, onsite_location | Remote, remote limited to one country, or on-site with its city |
proposal_count | Proposals sent so far |
is_urgent, is_featured, is_prefunded, is_opportunity, is_nda | The site's job badges |
attachments | File names the client attached |
client_id, client_name, client_public_name, client_url | Client as the site shows them, with profile link |
client_city, client_country, client_country_code, client_registered, client_photo, client_verified | Client location, member-since date, photo and verification badge |
query, source_url, scraped_at | Where the row came from and when |
Example from a test run (trimmed; client details replaced with fictional ones):
{
"project_id": 4527601,
"title": "WordPress Developer – 6-Page Bilingual Corporate Website",
"url": "https://www.peopleperhour.com/freelance-jobs/technology-programming/website-development/wordpress-developer-6-page-bilingual-corporate-website-4527601",
"description": "We require an experienced WordPress developer to create a professional, bilingual website for a property and land development business…",
"budget": 275,
"currency": "GBP",
"budget_converted": 369.09,
"budget_converted_currency": "USD",
"project_type": "fixed_price",
"budget_bracket": 3,
"experience_level": "Expert",
"category": "Technology & Programming",
"sub_category": "Website Development",
"posted_date": "2026-10-20 15:35:23",
"expiry_date": "2026-11-19 15:35:23",
"status": "open",
"is_open": true,
"location_type": "remote",
"proposal_count": 97,
"is_urgent": false,
"is_prefunded": false,
"is_opportunity": true,
"attachments": [],
"client_id": 10000001,
"client_name": "Laura M.",
"client_url": "https://www.peopleperhour.com/freelancer/laura-m-example",
"client_city": "Crawley",
"client_country": "United Kingdom",
"client_country_code": "GB",
"client_registered": "2019-11-20",
"client_verified": false,
"query": "wordpress",
"scraped_at": "2026-10-21T20:28:40Z"
}
Is it legal to scrape PeoplePerHour? The actor reads only public job listings that anyone can see without an account. You are responsible for how you use the data; check the site's terms and your local laws, especially for personal data.
Do I need a PeoplePerHour account or a proxy? No login. The default datacenter proxy works; if the site ever refuses it, the run switches to UK residential exits by itself.
How many jobs can I get? As many as the site lists for your search: usually several hundred open jobs in total, and up to 10,000 per search with closed jobs included. Set maxItems to 0 for everything.
Why is a field empty? Fields appear only when the job has them: remote_country only for jobs limited to one country, onsite_location only for on-site jobs, client_photo only when the client uploaded one, and query only for keyword searches.
What does the keyword search match? The site's own search, which also matches related words in titles and descriptions. Use the filters, or sortBy: relevance, for tighter results.
Can I schedule it or use the API? Yes. Schedule runs (e.g. hourly with postedWithinDays: 1) and fetch results through the API or integrations. Each job is saved once per run, even when several keywords find it.
posted_date and expiry_date are given as the site shows them, without a time zone.Every field below can be set in the run form, passed through the API, or saved as a task. Unset fields fall back to the defaults shown.
queriesarrayOptionalSearch keywords
Keywords to search freelance jobs for, one per line (e.g. 'wordpress', 'logo design', 'python'). Each keyword is its own search. Leave empty to list every job that matches the filters below.
startUrlsarrayOptionalPeoplePerHour links
Job search or category links (peopleperhour.com/freelance-jobs, /freelance-jobs/technology-programming, /freelance-jobs/design/logo-design, search links with ?keyword=...) or single job links (peopleperhour.com/freelance-jobs///-). Each search link is its own search with the filters it shows on the site.
maxItemsintegerOptionaldefault 20Max jobs per search
How many jobs to save per keyword or search link. 0 means everything the site lists. The site serves at most 10,000 jobs per search (200 pages); narrow the search to go further.
categoryenumOptionaldefault "all"Category
Only jobs in this category (applies to keyword searches and to the filter-only search).
projectTypeenumOptionaldefault "all"Pricing
Fixed-price jobs, hourly jobs, or both.
experienceLevelsarrayOptionalExperience level
Only jobs for these experience levels (the site's budget bracket). Empty means every level.
minBudgetintegerOptionalMin budget (USD)
Keep jobs whose budget (converted to US dollars by the site) is at least this amount. For hourly jobs this is the hourly rate.
maxBudgetintegerOptionalMax budget (USD)
Keep jobs whose budget in US dollars is at most this amount.
maxProposalsintegerOptionalMax proposals
Keep jobs with at most this many proposals so far (e.g. 5 to find jobs with little competition).
postedWithinDaysintegerOptionalPosted within (days)
Keep jobs posted in the last N days (e.g. 3). Empty or 0 means any time.
remoteOnlybooleanOptionaldefault falseRemote jobs only
Skip on-site jobs.
urgentOnlybooleanOptionaldefault falseUrgent jobs only
Only jobs the client marked as urgent.
preFundedOnlybooleanOptionaldefault falsePre-funded jobs only
Only jobs whose budget the client has already paid in.
opportunityOnlybooleanOptionaldefault falseOpportunity jobs only
Only jobs the site flags as high-value opportunities.
noProposalsOnlybooleanOptionaldefault falseJobs with no proposals only
Only jobs nobody has sent a proposal to yet.
includeClosedJobsbooleanOptionaldefault falseInclude closed jobs
Also return jobs that are no longer open (in progress, completed or expired), for market research on past demand and budgets.
sortByenumOptionaldefault "newest"Sort by
Order in which the site returns jobs. With 'Newest first', a 'Posted within' filter stops as soon as older jobs begin.
proxyConfigurationobjectOptionaldefault {"useScrapelyProxy":true,"scrapelyProxyGroups":["DATACENTER…Proxy
Datacenter exits work well for peopleperhour.com. If the site refuses them, the run switches to UK residential exits by itself.
Every run writes its results to a dataset. Preview it in the dashboard, then export it or read it through the API.
| Field | Type | Description |
|---|---|---|
| project_id | number | null | PeoplePerHour job id |
| title | string | null | |
| url | string | null | |
| description | string | null | Full job description |
| budget | number | null | Budget in the client's currency (hourly rate for hourly jobs) |
| currency | string | null | |
| budget_converted | number | null | Budget converted to US dollars by the site |
| budget_converted_currency | string | null | |
| project_type | string | null | fixed_price or hourly |
| budget_bracket | number | null | 1 entry, 2 intermediate, 3 expert |
| experience_level | string | null | |
| category | string | null | |
| category_slug | string | null | |
| sub_category | string | null | |
| sub_category_slug | string | null | |
| posted_date | string | null | As the site shows it (YYYY-MM-DD HH:MM:SS) |
| expiry_date | string | null | |
| status | string | null | open, in_progress, completed, expired... |
| is_open | boolean | null | |
| location_type | string | null | remote, remote_country or onsite |
| remote_country | string | null | Country a remote job is limited to |
| onsite_location | string | null | |
| proposal_count | number | null | |
| is_urgent | boolean | null | |
| is_featured | boolean | null | |
| is_prefunded | boolean | null | |
| is_opportunity | boolean | null | |
| is_nda | boolean | null | |
| attachments | array | null | File names the client attached |
| client_id | number | null | |
| client_name | string | null | As the site shows it (first name and initial) |
| client_public_name | string | null | |
| client_url | string | null | |
| client_country | string | null | |
| client_country_code | string | null | |
| client_city | string | null | |
| client_registered | string | null | Date the client joined |
| client_photo | string | null | |
| client_verified | boolean | null | |
| query | string | null | Search keyword that found the job |
| source_url | string | null | Link the job came from |
| scraped_at | string | null |
You pay for the events the actor reports, such as each result or page it produces. Platform usage is included in the event prices.
| Event | Charged when | Price |
|---|---|---|
| Job | One saved PeoplePerHour job. | $0.003 |
Run this actor from your own code. Swap in your API token and the examples work as-is.
import { ScrapelyClient } from 'scrapely-client'
const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN })
// Start the actor and wait for the run to finish.
const run = await client.actor('openrole/peopleperhour-scraper').call({
"queries": [
"wordpress"
],
"maxItems": 20,
"proxyConfiguration": {
"useScrapelyProxy": true,
"scrapelyProxyGroups": [
"DATACENTER"
]
}
})
// Read the dataset the run produced.
const { items } = await client.dataset(run.defaultDatasetId).listItems()
console.log(items)Tokens live in your account settings. Keep them server-side: a token carries the full permissions of your account.
Connect the Scrape.ly MCP server once and your agent can run this actor as a tool. Pick your tool:
Fetch scrape.ly/agents.md and run openrole/peopleperhour-scraperPaste into Claude Code, Codex, Cursor or any AI agent. It signs you in once in the browser.
{
"mcpServers": {
"scrapely": {
"url": "https://api.scrape.ly/mcp?tools=actors,runs,storage,docs&actors=openrole/peopleperhour-scraper"
}
}
}No key in the file: your client opens the browser to sign you in the first time it connects.
Inputs the developer prepared for common jobs. Open one to see its input, then copy it to your account to run it as-is or adjust it.
Fixed-price jobs for a keyword, with budgets in GBP/USD and client details.
Newest jobs from one PeoplePerHour category link.
Jobs from a sub-category link.
Past and open jobs in one category for market research.
Full details for specific job pages.
Filter-only search with a budget floor and a date window.
Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.