PeoplePerHour Job Scraper avatar

PeoplePerHour Job Scraper

Pricing

from $1.00 / 1,000 job founds

Go to Apify Store
PeoplePerHour Job Scraper

PeoplePerHour Job Scraper

PeoplePerHour Job Scraper extracts open freelance jobs by keyword, category slug, or listing URL. Each row is one project: title, full brief, budget, client name and city, proposal count, and urgency badges. No login. Hourlies, profiles, and job-detail URLs stay out of scope.

Pricing

from $1.00 / 1,000 job founds

Rating

0.0

(0)

Developer

Muhamed Didovic

Muhamed Didovic

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Turn any PeoplePerHour keyword, category, or /freelance-jobs listing into structured freelance-job rows.

Start from a search term, a category slug, or a listing URL. Each row is one open project: title, full brief, budget, client, proposals, and badges. No PeoplePerHour login.

How the PeoplePerHour Job Scraper works

Why Use This Scraper?

  • Multiple entry points — keywords, category slugs, or listing URLs in one run
  • Full project brief on every row (it already lives in the listing JSON)
  • Client name, city, country, and public profile URL
  • Budget in native currency plus converted amount, fixed or hourly
  • Proposal counts and urgency / featured / opportunity / pre-funded badges
  • Accepts the common queries + item_limit input aliases
  • One row per projectId, billed per job written

Overview

Built for freelancers, agencies, and researchers who need a feed of open PeoplePerHour projects — not hourlies (fixed-price services) and not freelancer profiles.

Every start type resolves to the same row shape: one job. A category URL and a keyword search both emit project rows. Job detail URLs are skipped because PeoplePerHour only embeds the job JSON on listing pages.

Supported Inputs

URL types

URL typePatternExample
Jobs board/freelance-jobshttps://www.peopleperhour.com/freelance-jobs
Category listing/freelance-jobs/{slug}https://www.peopleperhour.com/freelance-jobs/technology-programming
Keyword search/freelance-jobs?keyword=https://www.peopleperhour.com/freelance-jobs?keyword=wordpress

Copy-pasteable startUrls

{
"startUrls": [
{ "url": "https://www.peopleperhour.com/freelance-jobs" },
{ "url": "https://www.peopleperhour.com/freelance-jobs/design" }
]
}

Keyword / search mode

{
"searchQueries": ["wordpress", "logo design"],
"maxItems": 50,
"sortBy": "latest"
}

Unsupported inputs

  • Job detail URLs (/freelance-jobs/{cat}/{sub}/{slug}-{id}) — no job JSON on that page
  • Hourlie / service listing URLs (/services, /hourlies)
  • Freelancer profile URLs (/freelancer/...)
  • Hosts outside peopleperhour.com
  • ?q= search — that query param does not filter on this site; use keyword

Use Cases

AudienceUse case
FreelancersWatch fresh projects that match a skill keyword and bid while proposal counts are still low
AgenciesFeed outbound / proposal workflows with client name, country, and budget
Market researchersTrack demand, budgets, and category mix on a UK-facing freelance board
RecruitersSee which skills clients ask for, and how they price the work
AggregatorsNormalize PeoplePerHour jobs into a shared jobs feed

How It Works

  1. Build listing URLs from searchQueries, categorySlugs, and pasted startUrls.
  2. Fetch each page over HTTP (impit, got-scraping, and impers race; first 200 wins).
  3. Parse window.PPHReact.initialState — the Redux blob with entities.projects.
  4. Walk ?page=N (20 jobs per page) until maxItems or the last page.
  5. Dedupe by projectId, write the row, charge job-found.

Default proxy is Apify RESIDENTIAL pinned to GB. Datacenter exits have returned HTTP 202 on this site in the cloud.

Input Configuration

FieldTypeRequiredNotes
searchQueriesstring[]noEach value becomes ?keyword=. Example: wordpress. Default: none.
categorySlugsstring[]noPath slugs: artificial-intelligence, technology-programming, writing-translation, design, digital-marketing, video-photography, business, music-audio, marketing-branding-sales, social-media.
startUrlsurl[]noListing / category / search URLs. Job detail URLs are skipped.
sortByenumnolatest (default), popularity, ending, budget, relevance. Applied to keyword and category searches.
priceTypeenumnofixed_price or hourly. Omit for both.
experienceLevelenumnoentry, intermediate, or expert. Omit for all. Applied to every listing, including pasted URLs.
postedWithinenumno24h, 7d, or 30d. Omit for any age. On sort=latest, paging stops once a page is older than the window.
remoteOnlybooleannoDefault false. Restricts keyword/category searches to remote projects.
onlyUniqueProjectsbooleannoDefault true. Dedupes by projectId across the run.
includeDescriptionbooleannoDefault true. Set false for title/budget/client/URL-only rows.
maxItemsintegernoHard cap on jobs written and billed. Default 50.
maxConcurrencyintegernoDefault 6. Pagination stays sequential so the cap is exact.
proxyobjectnoDefault Apify RESIDENTIAL + country GB.

Aliases accepted in the JSON input (not shown as separate Console fields): queries → searchQueries, item_limit → maxItems.

Example — keyword

{
"searchQueries": ["wordpress"],
"maxItems": 50,
"sortBy": "latest"
}

Example — category listing

{
"startUrls": [
{ "url": "https://www.peopleperhour.com/freelance-jobs/digital-marketing" }
],
"maxItems": 30
}

Example — hourly + remote

{
"searchQueries": ["data entry"],
"priceType": "hourly",
"remoteOnly": true,
"maxItems": 20
}

Example — expert jobs from the last day

{
"searchQueries": ["wordpress"],
"experienceLevel": "expert",
"postedWithin": "24h",
"sortBy": "latest",
"maxItems": 20
}

Output Overview

One flat row per project. The listing blob already includes the full brief and nested client, so there is no second hop and no separate client dataset.

experienceLevel is derived from PeoplePerHour's budget bracket (1 entry, 2 intermediate, 3 expert). Skill tags are not on the listing JSON and stay absent.

Output Samples

Keyword run (searchQueries: ["wordpress"]), trimmed from a live row:

{
"projectId": "4522678",
"title": "Website & Payment Portal Design - Wordpress",
"url": "https://www.peopleperhour.com/freelance-jobs/design/web-design/website-payment-portal-design-wordpress-4522678",
"description": "I am looking to build a relatively basic website for my refurbishment & maintenance business…",
"budget": 2500,
"budgetConverted": 3355.32,
"budgetBracket": 3,
"currency": "GBP",
"projectType": "fixed_price",
"experienceLevel": "expert",
"locationType": "remote",
"category": "Design",
"subCategory": "Web Design",
"postedDate": "2026-09-21T09:33:58.000Z",
"proposalCount": 49,
"isUrgent": false,
"isFeatured": false,
"isOpportunity": false,
"isPreFunded": false,
"clientName": "Calum N.",
"clientCity": "Glasgow",
"clientCountry": "United Kingdom",
"clientUrl": "https://www.peopleperhour.com/freelancer/calum-zxmqnqay",
"searchQuery": "wordpress"
}

Key Output Fields

Job

  • projectId — stable PeoplePerHour project id
  • title, url, description
  • postedDate, expiryDate — ISO-8601
  • searchQuery, sourceUrl — which input produced the row

Money

  • budget, budgetConverted, currency
  • projectType — fixed_price or hourly
  • budgetBracket / experienceLevel — entry / intermediate / expert

Client

  • clientName, clientCity, clientCountry, clientCountryCode
  • clientUrl, clientId

Activity

  • proposalCount, unreadProposalCount
  • isUrgent, isFeatured, isOpportunity, isPreFunded
  • locationType, whereCanBid, duration

FAQ

Do I need a PeoplePerHour account? No. The actor reads public listing pages only.

Why were my job URLs skipped? Detail pages hydrate empty. Paste /freelance-jobs, a category page, or use searchQueries.

Does q=wordpress work? No. Use keyword (the searchQueries field). q returns the unfiltered board.

Are skill tags included? No. They are not in the listing JSON. The full brief, budget, client, and badges are.

Does it scrape hourlies or freelancer profiles? No. Jobs only.

What does a run cost? $0.005 per GB of memory at start (default after publish is 512 MB → one start event) plus $0.001 per job written. Empty rows are not charged.

What proxy should I use? Keep the default: Apify residential, country GB. Datacenter proxies have returned HTTP 202 on listing URLs in the cloud.

Support

Open an issue on this actor's Issues tab in the Apify Console. Bugs and field requests are welcome.

Additional Services

Need a scheduled lead feed, extra fields, or a push into a CRM / warehouse? Custom work is available via the Issues tab.

Explore More Scrapers

The rest of the portfolio is on the memo23 Store page.

🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the Apify MCP server or the Apify API (actor: memo23/peopleperhour-job-scraper).

Purpose: Scrapes public PeoplePerHour freelance jobs (not hourlies, not profiles) into one dataset row per project.

Minimal input:

{
"searchQueries": ["wordpress"],
"maxItems": 25
}

Output: one row per job — projectId, title, url, description, budget, budgetConverted, currency, projectType, experienceLevel, locationType, category, subCategory, postedDate, expiryDate, proposalCount, isUrgent, isFeatured, isOpportunity, isPreFunded, clientName, clientCity, clientCountry, clientUrl, searchQuery.

Behaviors an agent should know:

  • Always set maxItems (default 50). It is the hard cap on rows and on job-found charges. Filtered-out jobs are not charged.
  • experienceLevel is entry, intermediate, or expert. postedWithin is 24h, 7d, or 30d. Omit either to skip that filter.
  • searchQueries, categorySlugs, and startUrls can be mixed; each keyword and each category is its own listing crawl.
  • Job detail URLs in startUrls are skipped. Use listing/search/category URLs only.
  • queries and item_limit are accepted aliases for searchQueries and maxItems.
  • Skills are not returned. No login, no cookies.
  • Billed job-found per written row plus apify-actor-start per GB of memory. Empty runs do not charge per-job events.

⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by PeoplePerHour Ltd or any of its subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available freelance-job listing pages — no authenticated endpoints, bidder inboxes, or content behind a PeoplePerHour login. Users are responsible for ensuring their use complies with PeoplePerHour's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation. Do not use results to spam clients.


SEO Keywords

PeoplePerHour scraper, PeoplePerHour job scraper, PeoplePerHour jobs API, scrape PeoplePerHour, Apify PeoplePerHour, PPH job scraper, freelance jobs scraper, PeoplePerHour projects, PeoplePerHour budget data, gig economy scraper, freelance marketplace data, PeoplePerHour proposals, PeoplePerHour category scrape, Fiverr alternative jobs scraper, Upwork alternative jobs data, PeoplePerHour lead generation, scrape freelance jobs UK, PeoplePerHour JSON export