# Handshake Jobs Scraper (`parsebird/handshake-jobs-scraper`) Actor

Scrape Handshake job and internship listings: job title, company, location, salary, employment type, posted date, industry, and full description. Export to JSON, CSV, or Excel.

- **URL**: https://apify.com/parsebird/handshake-jobs-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.89 / 1,000 job scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### Handshake Jobs Scraper — Job Listings from Handshake

Scrape job and internship listings from [Handshake](https://joinhandshake.com/) — the career network built for students and early-career talent, with over 50,000 active postings from employers across every industry. Extract job titles, companies, locations, salaries, employment type, posted dates, industries, and full descriptions. Search by keyword, city, employment type, and posting recency. Export as JSON, CSV, or Excel.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search Handshake's public job and internship board by keyword, city, country, company, employment type, and posting date — get structured job data with salary ranges and full descriptions ready for analysis, monitoring, or integration.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
Apify Actor: parsebird/handshake-jobs-scraper — scrapes joinhandshake.com public job and internship listings. $0.99/1000 results on the Free plan, $0.89/1000 on Bronze/Silver/Gold plans. Call via ApifyClient: client.actor("parsebird/handshake-jobs-scraper").call(run_input={"includeKeyword": "software engineer", "locationName": "New York, NY", "pagesToFetch": 3}). Inputs: includeKeyword (string, required — job title, skill, or comma-separated search phrases), locationName (string, optional — city, state, or "remote"), countryName (string, default "all"), companyName (string, optional — filters by employer name), jobType (enum: ANY|FULLTIME|PARTTIME|CONTRACTOR|INTERN, default ANY), datePosted (enum: today|3days|week|month, default month), pagesToFetch (integer, default 1, max 20, each page returns up to 20 jobs), proxyConfiguration (object, optional). Output: dataset with job_title, company_name, location, is_remote, posted_via, salary, salary_min, salary_max, salary_currency, salary_period, date, posted_at, valid_through, job_type, industry, job_id, employer_website, employer_logo, description, URL. API docs: https://docs.apify.com/api/v2 Token: https://console.apify.com/settings/integrations
```

### What is Handshake Jobs Scraper?

**Handshake Jobs Scraper** is an [Apify Actor](https://apify.com/actors) that extracts job and internship postings from [Handshake](https://joinhandshake.com/) — the largest early-career job platform in the US, used by more than 15 million students and alumni across 1,500+ universities. It pulls structured data straight from Handshake's own public job pages, including salary ranges, employment type, and full job descriptions, without needing a Handshake account.

Think of it as a **Handshake jobs API alternative** — Handshake has no public API for bulk job search, but this scraper delivers the same structured job data programmatically. It's built for recruitment analytics, early-career labor market research, and lead generation across Handshake's employer base.

### What can Handshake Jobs Scraper do?

- 🔍 **Keyword search** — search any job title, skill, or phrase, with comma-separated terms treated as alternatives
- 📍 **Location filtering** — scope results to a specific US city, or search remote-only postings
- 🌎 **Country filtering** — keep only postings located in a specific country
- 🏢 **Company filtering** — narrow results down to a single employer
- 💼 **Employment type** — filter by full-time, part-time, contract, or internship
- 📅 **Recency filtering** — restrict results to jobs posted today, in the last 3 days, week, or month
- 💰 **Salary extraction** — pulls minimum, maximum, currency, and pay period whenever the employer publishes a range
- 📄 **Full job descriptions** — clean, plain-text descriptions for every posting
- ⏱️ **Scheduling & API access** — run on autopilot with [Apify Schedules](https://docs.apify.com/platform/schedules) and pull results via the [Apify API](https://docs.apify.com/api/v2) or client libraries
- 📊 **Multiple export formats** — download as JSON, CSV, Excel, XML, HTML, or RSS

### What data can you extract from Handshake?

| Field | Description |
|-------|-------------|
| `job_title` | The official title of the role |
| `company_name` | The hiring organization |
| `location` | City/state, or "Remote" |
| `is_remote` | Boolean flag for remote postings |
| `salary` | Formatted pay range or single amount, with currency and period |
| `salary_min` / `salary_max` | Parsed numeric salary bounds |
| `job_type` | Full-time, Part-time, Internship, or Contract |
| `date` | Date the job was posted (ISO 8601) |
| `valid_through` | Date the posting expires |
| `industry` | Employer's listed industry |
| `posted_via` | Original source platform, where Handshake aggregates external postings |
| `employer_website` | Employer's website |
| `description` | Full plain-text job description |
| `URL` | Direct link to the Handshake job page |

### How to scrape Handshake job listings

1. **Go to Handshake Jobs Scraper** on [Apify Store](https://apify.com/parsebird/handshake-jobs-scraper) and click **Try for free**
2. **Enter a keyword** — e.g. "software engineer", "marketing", "registered nurse"
3. **Optionally set a location** — a US city like "New York, NY", or "remote"
4. **Optionally filter by company, employment type, or posting date**
5. **Set pages to fetch** — start with 1 page (20 jobs) for a quick test, increase for larger datasets
6. **Run the Actor** — click **Start** and wait for results
7. **Export your data** — download as JSON, CSV, or Excel, or access via the [Apify API](https://docs.apify.com/api/v2)

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `includeKeyword` | string | **Yes** | — | Job title, skill, or search phrase. Comma-separate multiple terms |
| `locationName` | string | No | — | City, state, or "remote" |
| `countryName` | string | No | `all` | Restrict results to a specific country |
| `companyName` | string | No | — | Filter by employer name |
| `jobType` | string | No | `ANY` | `ANY`, `FULLTIME`, `PARTTIME`, `CONTRACTOR`, or `INTERN` |
| `datePosted` | string | No | `month` | `today`, `3days`, `week`, or `month` |
| `pagesToFetch` | integer | No | `1` | Number of result pages to collect (max 20). Each page returns up to 20 jobs |
| `proxyConfiguration` | object | No | `{"useApifyProxy": false}` | Optional Apify Proxy configuration for large collections |

### Output example

```json
[
  {
    "job_title": "Software Engineer",
    "company_name": "Rilla",
    "location": "New York City, NY",
    "is_remote": false,
    "posted_via": "Handshake",
    "salary": "$200,000 - $285,000 a year",
    "salary_min": 200000,
    "salary_max": 285000,
    "salary_currency": "USD",
    "salary_period": "Year",
    "date": "2026-08-05",
    "valid_through": "2026-09-05",
    "job_type": "Full-time",
    "industry": "Internet & Software",
    "employer_website": "https://www.rilla.com",
    "description": "Rilla is on a mission to index the offline world...",
    "URL": "https://app.joinhandshake.com/public/jobs/11277749"
  }
]
```

Download results in JSON, CSV, Excel, XML, HTML, or RSS, or access via the [Apify API](https://docs.apify.com/api/v2).

### Use cases

- 📊 **Recruitment intelligence** — build hiring datasets across Handshake's employer base, filtered by role, location, and industry
- 🎓 **Early-career labor market research** — track entry-level and internship hiring trends by city, industry, or employment type
- 🎯 **Sales prospecting** — find companies actively hiring on Handshake and enrich outreach lists with role and company context
- 📅 **Job market monitoring** — schedule recurring runs and combine with `datePosted` to track new postings only
- 🔌 **Pipeline integration** — feed job data into Google Sheets, Slack, Zapier, Make, or custom systems via [Apify Integrations](https://docs.apify.com/platform/integrations)
- 🤖 **Training data collection** — build datasets of structured job postings for NLP, resume matching, or recommendation systems

### How it works

1. The Actor matches your `includeKeyword` and `locationName` to the closest Handshake listing pages (role pages like `/find-jobs/role/software-engineering/`, city pages, or internship pages) and collects candidate job IDs
2. Each candidate job is fetched individually from its public Handshake page and parsed for salary, location, employment type, and full description
3. Results are filtered against your `companyName`, `countryName`, `jobType`, and `datePosted` inputs, then ranked so the closest keyword matches come first
4. Every job is pushed to the dataset as it's collected, so partial results are available even if a run is stopped early

### How to use via API — Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("parsebird/handshake-jobs-scraper").call(run_input={
    "includeKeyword": "data analyst",
    "locationName": "Chicago, IL",
    "jobType": "FULLTIME",
    "datePosted": "week",
    "pagesToFetch": 3,
})

for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"{job['job_title']} at {job['company_name']} — {job['location']} — {job['salary']}")
```

### How to use via API — JavaScript

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('parsebird/handshake-jobs-scraper').call({
    includeKeyword: 'data analyst',
    locationName: 'Chicago, IL',
    jobType: 'FULLTIME',
    datePosted: 'week',
    pagesToFetch: 3,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach(job => {
    console.log(`${job.job_title} at ${job.company_name} — ${job.location} — ${job.salary}`);
});
```

### How much does it cost to scrape Handshake?

Handshake Jobs Scraper uses [pay-per-event pricing](https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event) — you pay a fixed price per job scraped. Platform usage (compute, proxy) is not charged separately.

**How much does it cost to scrape 1,000 Handshake jobs?**

$0.99 on the Free plan, or $0.89 on Bronze, Silver, and Gold Apify plans. New users get a free trial with platform credit to try the Actor before committing.

**How much does it cost to scrape 100 Handshake jobs?**

Around $0.10 on the Free plan — a quick export covering one keyword and location.

### Pricing

| Event | Price per event (Free) | Price per event (Bronze/Silver/Gold) | Price per 1,000 |
|-------|------------------------|----------------------------------------|------------------|
| `job-scraped` | $0.00099 | $0.00089 | **$0.99 / $0.89** |

Each job pushed to the dataset — including its full description — counts as one event.

### Is it legal to scrape Handshake?

This Actor extracts publicly available data from Handshake's public job pages (`joinhandshake.com/find-jobs`, `joinhandshake.com/internships`, and `app.joinhandshake.com/public/jobs/...`) — the same listing data any visitor can see without logging in.

Web scraping of publicly available data is generally legal in the United States and the European Union, as established by the [hiQ Labs v. LinkedIn ruling](https://en.wikipedia.org/wiki/HiQ_Labs_v._LinkedIn). For more information, see Apify's guide on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

Users are responsible for ensuring their use of extracted data complies with applicable laws and Handshake's Terms of Service in their jurisdiction.

### Related Actors

Looking for more job scraping and data extraction tools? Check out these ParseBird actors:

- [Hiring.cafe Jobs Scraper](https://apify.com/parsebird/hiring-cafe-scraper) — Scrape job listings from Hiring.cafe with 20+ filters
- [Wellfound Jobs Scraper](https://apify.com/parsebird/wellfound-jobs-scraper) — Scrape startup and tech job listings from Wellfound
- [Y Combinator Jobs Scraper](https://apify.com/parsebird/yc-jobs-scraper) — Scrape Y Combinator startup job listings
- [Himalayas Remote Jobs Scraper](https://apify.com/parsebird/himalayas-remote-jobs-scraper) — Scrape remote job listings from Himalayas
- [Workable Job Scraper](https://apify.com/parsebird/workable-job-scraper) — Scrape job listings from companies hiring through Workable

Browse all [ParseBird actors on Apify Store](https://apify.com/parsebird).

### FAQ

**Why do some jobs show no salary?**
Handshake only displays a salary range when the employer chooses to publish one. When it's missing, `salary`, `salary_min`, and `salary_max` are empty.

**What does `posted_via` mean?**
Handshake aggregates some postings from other job boards and applicant tracking systems (for example LinkedIn, Greenhouse, or a company's own careers page). `posted_via` names the original source when Handshake exposes it; it defaults to "Handshake" for postings created directly on the platform.

**Can I search for remote jobs specifically?**
Yes. Set `locationName` to `"remote"`. Results are also matched against each job's actual location data, so hybrid or on-site roles that merely mention "remote-friendly" in the title are not included.

**Why does "Today" or "Last 3 days" sometimes return fewer jobs than expected?**
Handshake rebuilds its public listing pages in batches rather than continuously, so the newest available posting can be a day or two behind the current date. The Actor measures these short windows from the freshest posting it can actually find, not from the current server time, so results stay meaningful even right after a rebuild.

**How does the Contract filter work?**
Handshake's own data only classifies postings as full-time, part-time, or internship — there's no separate "contract" flag. When `jobType` is set to `CONTRACTOR`, the Actor also matches postings whose title mentions contract, temporary, seasonal, or freelance work.

**What happens if a search returns no jobs?**
The Actor finishes successfully with an empty dataset and logs a warning — this isn't treated as an error. Try a broader keyword, or remove the company, location, or date filters.

**Can I schedule recurring runs?**
Yes. Use [Apify Schedules](https://docs.apify.com/platform/schedules) to run daily, weekly, or at any interval, and combine with `datePosted` to track only new postings.

**Can I access the data via API?**
Yes. Use the [Apify API](https://docs.apify.com/api/v2) or the official [Python](https://docs.apify.com/api/client/python) and [JavaScript](https://docs.apify.com/api/client/js) client libraries to run the Actor and retrieve results programmatically.

**What export formats are supported?**
JSON, CSV, Excel (XLSX), XML, HTML, and RSS. Download directly from the Apify Console or via the API.

**Is there a free trial?**
Yes. New Apify users get free platform credit to try Handshake Jobs Scraper before committing to a paid plan.

**I found an issue or have a feature request.**
Open an issue on the [Issues tab](https://apify.com/parsebird/handshake-jobs-scraper/issues) or contact ParseBird via the Apify Console.

# Actor input Schema

## `includeKeyword` (type: `string`):

Enter a job title, skill, or search phrase. Separate several searches with commas — a job is kept when it matches any of them.

## `locationName` (type: `string`):

Enter a city, state, or "remote". Handshake publishes city pages for 94 US metros, so "New York, NY" or "Chicago" work best.

## `countryName` (type: `string`):

Keep only postings located in this country. Use "all" for no country filter. Handshake's public job feed is overwhelmingly US-based.

## `companyName` (type: `string`):

Keep only postings from employers whose name contains this text, for example "Kaiser" or "Deloitte". Leave empty for all employers.

## `jobType` (type: `string`):

Choose an employment type. Internship pulls from Handshake's internship listings; the other options filter regular job postings.

## `datePosted` (type: `string`):

Keep only jobs first published on Handshake within this window.

## `pagesToFetch` (type: `integer`):

Number of result pages to collect. Each page returns up to 20 jobs, so 3 pages returns up to 60 jobs.

## `proxyConfiguration` (type: `object`):

Optional Apify Proxy configuration. Not required for normal runs; useful for very large collections.

## Actor input object example

```json
{
  "includeKeyword": "software engineer",
  "locationName": "New York, NY",
  "countryName": "all",
  "companyName": "",
  "jobType": "ANY",
  "datePosted": "month",
  "pagesToFetch": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "includeKeyword": "software engineer",
    "locationName": "New York, NY",
    "countryName": "all",
    "companyName": "",
    "jobType": "ANY",
    "datePosted": "month",
    "pagesToFetch": 1,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/handshake-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 = {
    "includeKeyword": "software engineer",
    "locationName": "New York, NY",
    "countryName": "all",
    "companyName": "",
    "jobType": "ANY",
    "datePosted": "month",
    "pagesToFetch": 1,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/handshake-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 '{
  "includeKeyword": "software engineer",
  "locationName": "New York, NY",
  "countryName": "all",
  "companyName": "",
  "jobType": "ANY",
  "datePosted": "month",
  "pagesToFetch": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call parsebird/handshake-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/handshake-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/vRQqNM05eqFfhqq98/builds/VUvWlDafdZ9dl9r9E/openapi.json
