Handshake Public Jobs Scraper avatar

Handshake Public Jobs Scraper

Pricing

Pay per event

Go to Apify Store
Handshake Public Jobs Scraper

Handshake Public Jobs Scraper

Extract anonymous public Handshake jobs with employers, role groups, remote locations, salaries, dates, and full descriptions. No login required. Export to JSON, CSV, Excel, or API and schedule recurring hiring-market refreshes.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

5

Monthly active users

6 days ago

Last modified

Categories

Share

Extract public Handshake jobs without a login or API key. Handshake Public Jobs Scraper turns anonymous Handshake search pages and public job URLs into structured recruiting data with employers, locations, remote status, compensation, dates, and full descriptions.

Use a public joinhandshake.com/find-jobs/ URL to discover openings, or submit specific app.joinhandshake.com/public/jobs/ URLs for targeted lookups. The Actor uses lightweight HTTP requests instead of a browser, deduplicates records by Handshake job ID, and exports results to JSON, CSV, Excel, XML, or RSS through Apify.

What does Handshake Public Jobs Scraper do?

Handshake Public Jobs Scraper combines two anonymous Handshake data surfaces:

  • 🔎 Public SEO job-search pages for discovery and search-level fields
  • 📄 Public job detail pages for complete Schema.org job-posting data
  • 💼 Employer names, websites, and logo URLs
  • 📍 City, state, and normalized remote status
  • 💰 Salary ranges, currency, unit, and pay schedule
  • 🗓️ First-active, posted, expiry, and scrape dates
  • 📝 Full description HTML plus clean plain text
  • 🔗 Canonical job and source-search URLs

No Handshake student, employer, or institution account is required. This Actor intentionally covers public jobs only; it does not claim personalized campus results or authenticated application data.

Who is it for?

Job-board operators

  • Refresh public early-career and graduate job inventories.
  • Import normalized records into a niche board or search index.
  • Detect newly posted and expired roles with scheduled runs.

Recruiters and sourcing teams

  • Build target lists from public Handshake searches.
  • Compare employers, role groups, locations, and compensation.
  • Route matching openings into a CRM, spreadsheet, or alert channel.

Campus and early-career teams

  • Monitor the anonymous job market visible outside institution accounts.
  • Track remote software and other public role categories.
  • Research employer hiring activity without manual copying.

Labor-market analysts and data teams

  • Collect repeatable snapshots for salary and hiring trend analysis.
  • Preserve posting and validity dates for time-series workflows.
  • Feed clean job descriptions into classification or language models.

Why use this Handshake jobs scraper?

  • No login or API key: works with the public pages users can open anonymously.
  • HTTP-first: avoids browser overhead and keeps runs fast and economical.
  • 🧩 Merged records: combines search hydration and job-detail JSON-LD.
  • 🔁 Deduplicated: the same job from multiple sources is saved once.
  • 🛡️ Resilient: retries temporary errors and skips one malformed job without losing the run.
  • 🎯 Flexible: use search URLs, direct job URLs, or both.
  • 📦 Export-ready: download JSON, CSV, Excel, XML, or RSS.
  • Automatable: schedule runs, trigger webhooks, or call through the API.

What Handshake job data can you extract?

CategoryFields
IdentityjobId, jobUrl, title
EmployeremployerName, employerWebsite, employerLogoUrl
ClassificationjobType, roleGroups, employmentType
Locationcity, state, isRemote
CompensationsalaryMin, salaryMax, salaryCurrency, salaryUnit, paySchedule
DatesfirstActiveAt, datePosted, validThrough, scrapedAt
ContentdescriptionHtml, descriptionText
ProvenancesourceSearchUrl

Fields remain null when a public posting does not publish that information. Salary numbers should always be interpreted together with paySchedule and salaryUnit; an hourly wage is not an annual salary.

How much does it cost to scrape Handshake jobs?

This Actor uses pay-per-event pricing. A small start charge covers initialization and search discovery, then each saved job is charged as one job event. Platform compute is included.

EventFreeStarterScaleBusiness
Run start$0.005$0.005$0.005$0.005
Job extracted$0.00010859$0.000094429$0.000073655$0.000056658

At these formula-validated prices, 100 jobs cost about $0.016 on Free or $0.014 on Starter, including the start event. A 1,000-job run costs about $0.114 on Free or $0.099 on Starter.

Apify Free users receive monthly platform credits, so a small evaluation can normally be completed from those credits. Higher plans receive additional volume discounts.

How to scrape public Handshake jobs

  1. Open Handshake Public Jobs Scraper on Apify.
  2. Paste one or more public joinhandshake.com/find-jobs/ URLs into Public job search URLs.
  3. Optionally add specific app.joinhandshake.com/public/jobs/{id} links.
  4. Set Maximum jobs to control output and cost.
  5. Choose whether to include descriptions or apply remote/salary filters.
  6. Click Start.
  7. Preview the dataset, then export it or connect an integration.

A small search example:

{
"searchUrls": [
{ "url": "https://joinhandshake.com/find-jobs/remote/software-engineering/" }
],
"maxItems": 10,
"includeDescriptions": true
}

A direct lookup example:

{
"jobUrls": [
{ "url": "https://app.joinhandshake.com/public/jobs/11196104" }
],
"maxItems": 1
}

A filtered monitoring example:

{
"searchUrls": [
{ "url": "https://joinhandshake.com/find-jobs/remote/software-engineering/" }
],
"maxItems": 100,
"remoteOnly": true,
"minSalary": 50
}

Input parameters

ParameterTypeDefaultDescription
searchUrlsarrayprefilled public searchPublic Handshake SEO search URLs used to discover job IDs.
jobUrlsarray[]Direct Handshake public job URLs for targeted lookups.
maxItemsinteger10Maximum matching jobs saved across all sources.
includeDescriptionsbooleantrueSave complete description HTML and normalized text.
remoteOnlybooleanfalseSave only jobs identified as remote.
minSalarynumberunsetRequire the published salary maximum to reach this threshold.

At least one search URL or job URL is required. URLs are validated to prevent accidental crawling of unrelated pages.

Output example

Each dataset row represents one public Handshake job:

{
"jobId": "11196104",
"jobUrl": "https://app.joinhandshake.com/public/jobs/11196104",
"title": "Applied AI Engineer",
"employerName": "Squoosh.AI",
"employerWebsite": "https://squoosh.ai/",
"employerLogoUrl": "https://handshake-production-cdn.joinhandshake.com/static_assets/default_institution_1.png",
"jobType": "Job",
"roleGroups": ["Software Developers and Engineers"],
"city": null,
"state": null,
"isRemote": true,
"salaryMin": 90000,
"salaryMax": 180000,
"salaryCurrency": "USD",
"salaryUnit": "YEAR",
"paySchedule": "Annually",
"firstActiveAt": "2026-07-10T02:01:30.000Z",
"datePosted": "2026-07-10T02:01:30Z",
"validThrough": "2026-08-09T03:59:59Z",
"employmentType": ["FULL_TIME"],
"descriptionHtml": "<p>Applied AI Engineer...</p>",
"descriptionText": "Applied AI Engineer...",
"sourceSearchUrl": "https://joinhandshake.com/find-jobs/remote/software-engineering/",
"scrapedAt": "2026-07-15T00:00:00.000Z"
}

When a direct job URL is supplied, sourceSearchUrl is null. When descriptions are disabled, both description fields are null.

Tips for best results

  • 🧪 Start with 5–10 jobs to validate your search and preferred fields.
  • 🔗 Use the exact public URL copied from Handshake rather than constructing a category slug.
  • 💰 Read salaryMin and salaryMax together with paySchedule and salaryUnit.
  • 📄 Keep descriptions enabled for semantic search, classification, or summarization.
  • ⚡ Disable descriptions when you only need search summaries and want smaller exports.
  • 🔁 Schedule searches daily or weekly, then deduplicate downstream by jobId.
  • ⏳ Treat validThrough as the source's advertised expiry, not a guarantee that an employer has not closed a role early.

Scheduling and monitoring jobs

Run the Actor on an Apify schedule to create regular snapshots. A practical workflow is:

  1. Save one task per public Handshake search URL.
  2. Run each task once per day.
  3. Export or webhook the dataset to your database.
  4. Upsert records by jobId.
  5. Alert when a previously unseen ID appears or when validThrough approaches.

The Actor does not maintain hidden cross-run state. This makes each result reproducible and lets your own datastore define new, changed, or expired records.

Integrations

Handshake jobs → Google Sheets

Append public openings to a recruiting tracker, then filter by employer, remote status, pay, or expiry date.

Handshake jobs → Slack or Discord

Schedule a targeted search and send newly observed job IDs to a campus recruiting or sourcing channel.

Handshake jobs → Make or Zapier

Trigger a workflow that enriches employers, creates CRM records, or assigns jobs to recruiters based on role groups.

Handshake jobs → database or data warehouse

Use webhooks or the API to upsert jobs by jobId and build time-series hiring dashboards.

Handshake jobs → AI pipeline

Send descriptionText to a classifier for skill extraction, seniority labeling, taxonomy mapping, or candidate matching.

API usage

Node.js

Install the client:

$npm install apify-client

Run the Actor and retrieve its dataset:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/handshake-public-jobs-scraper').call({
searchUrls: [{ url: 'https://joinhandshake.com/find-jobs/remote/software-engineering/' }],
maxItems: 25,
includeDescriptions: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Using the Apify API with Python

$pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/handshake-public-jobs-scraper').call(run_input={
'jobUrls': [{'url': 'https://app.joinhandshake.com/public/jobs/11196104'}],
'maxItems': 1,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)

Using the Apify API with cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~handshake-public-jobs-scraper/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"searchUrls": [{"url":"https://joinhandshake.com/find-jobs/remote/software-engineering/"}],
"maxItems": 10,
"remoteOnly": true
}'

Use the returned defaultDatasetId with the dataset items endpoint to download JSON, CSV, Excel, XML, or RSS.

Use Handshake Public Jobs Scraper with AI agents via MCP

This Actor can be used by AI assistants that support the Model Context Protocol.

For Claude Code:

$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/handshake-public-jobs-scraper"

For Claude Desktop, Cursor, or VS Code, add this MCP configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/handshake-public-jobs-scraper"
}
}
}

Example prompts:

  • “Use automation-lab/handshake-public-jobs-scraper to find 25 public remote software engineering jobs and summarize the salary ranges.”
  • “Extract this Handshake public job URL and tell me its employer, expiry date, employment type, and required skills.”
  • “Run my Handshake search, return only remote jobs above the published pay threshold, and prepare a CSV-ready table.”

OAuth connects the MCP server to your Apify account on first use.

Scraping publicly available business and job-posting data is generally lawful in many jurisdictions, but legality depends on your location, purpose, and handling of the data. This Actor accesses anonymous public pages only; it does not bypass login controls or collect private student data.

You are responsible for complying with Handshake's terms, applicable laws, robots guidance, privacy obligations, and employer content rights. Avoid using job data for discrimination, unsolicited spam, or decisions that require consent. Collect only what you need, retain it for an appropriate period, and honor deletion or correction obligations that apply to your workflow.

Limitations

  • Only anonymous public Handshake search and job-detail pages are supported.
  • Institution-personalized results, applications, and student or recruiter profiles are out of scope.
  • A search page may expose IDs for jobs that expire between discovery and detail retrieval; those jobs are logged and skipped.
  • Handshake decides which salary, location, and role fields are published, so optional values can be null.
  • The minimum-salary filter compares the numeric published maximum; always consider the pay schedule.
  • Public page structure can change. The Actor reports parsing failures rather than inventing values.
  • maxItems limits saved matching records, not the number of candidate URLs inspected when filters exclude jobs.

Troubleshooting

Why did my run return no jobs?

Confirm the URL opens anonymously and begins with https://joinhandshake.com/find-jobs/ or https://app.joinhandshake.com/public/jobs/. Remove filters temporarily, especially a high minSalary, and inspect the run log for expired jobs.

Why are salary or location fields empty?

The employer may not publish those fields. Null values reflect the source rather than an extraction error. Check the description for unstructured compensation text if your workflow permits text analysis.

Why did fewer jobs appear than Handshake's displayed total?

A job may expire after the search page is generated, or your remote/salary filters may exclude it. The Actor logs malformed or unavailable public detail pages and continues with other candidates.

How fast is it?

The Actor uses direct HTTP. Runtime mainly depends on the number of detail pages requested and their response latency. A five-job prefilled run should normally complete well under two minutes.

FAQ

Does this Actor require a Handshake account?

No. It supports only the public search and public job-detail pages that load without authentication.

Can I scrape a specific job instead of a search?

Yes. Add its app.joinhandshake.com/public/jobs/{id} URL to jobUrls. You can combine direct and search URLs in one run.

How are duplicate jobs handled?

Jobs are keyed by their numeric Handshake job ID. If the same ID occurs in several searches or direct inputs, it is saved once.

Can I monitor new jobs?

Yes. Schedule recurring runs and upsert downstream by jobId. Compare each snapshot with your previous one to identify newly observed jobs.

Is this the official Handshake API?

No. This independent Actor extracts structured data from anonymous public web pages. It is not affiliated with or endorsed by Handshake.

What counts toward maxItems?

Only complete records that pass your filters and are saved to the dataset count toward the limit.

Other recruiting and jobs scrapers

Combine this Actor with other Automation Labs tools:

Use only related tools that fit your data source and verify each target's public availability before building a multi-source workflow.