# Handshake Jobs Scraper: Job & Internship Listings (`getascraper/handshake-jobs-scraper`) Actor

Scrape public Handshake job and internship listings by keyword, location, role, employer, employment type, workplace status, date posted, and compensation. Export titles, employers, salaries, deadlines, and application links. No login required.

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

## Pricing

from $0.06 / 1,000 job postings

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 & Internship Listings

<table width="100%">
<tr>
<td style="padding:24px 28px;background:#F0FDFA;border:1px solid #99F6E4;border-top:4px solid #0F766E;border-radius:12px">
<span style="font-size:23px;font-weight:800;color:#1C1917;line-height:1.3">Get live Handshake job and internship listings, salary, and deadlines, ready for your spreadsheet in minutes.</span><br>
<span style="font-size:15px;color:#57534E;line-height:1.6">Pull public Handshake postings by keyword, role, location, or employer. No Handshake account needed on either side.</span>
</td>
</tr>
</table>

<table width="100%">
<tr>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #99F6E4;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#0F766E">💰 Salary with schedule</span><br>
<span style="font-size:12px;color:#57534E">See minimum and maximum pay, per hour or per year, in the listing's own currency, before you click through.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #99F6E4;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#0F766E">⏳ Deadline visibility</span><br>
<span style="font-size:12px;color:#57534E">Every detailed listing carries its application deadline, so you know exactly how long a role stays open.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #99F6E4;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#0F766E">📍 Remote or on site</span><br>
<span style="font-size:12px;color:#57534E">Filter by workplace status and employment type without opening a single listing.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #99F6E4;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#0F766E">🔓 No account needed</span><br>
<span style="font-size:12px;color:#57534E">Runs entirely on public Handshake pages. No login, no cookies, no account to maintain.</span>
</td>
</tr>
</table>

**Handshake Jobs Scraper** collects public job and internship listings from [joinhandshake.com](https://joinhandshake.com/find-jobs/), the campus recruiting platform used by thousands of employers and universities. Search by keyword, role category, location, employer name, employment type, workplace status, posting date, and compensation range, and get back structured records with salary, deadline, and a direct application link. Run it once for a snapshot, or schedule it on Apify to keep a live feed of new postings flowing into your dataset, spreadsheet, or internal tool.

### 🎯 Why use this Handshake scraper?

- **I am a campus recruiting lead** tracking which employers are posting new internships on Handshake, so I can see how our own roles compare on salary and application deadlines.
- **I am a university career services coordinator** mirroring live Handshake internship and new-grad listings onto our own job board, so students find every open role in one place.
- **I am a recruiting agency researcher** building a structured feed of early-career openings and deadlines, so my team can reach qualified candidates before a role closes.
- **I am a market researcher** tracking internship and new-grad pay by role, location, and employer, so I can publish accurate early-career compensation benchmarks.

### 🚀 How to use Handshake Jobs Scraper

<table width="100%">
<tr>
<td style="padding:16px 14px;width:33%;background:#F0FDFA;border:1px solid #99F6E4;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#0F766E;letter-spacing:1px">STEP 1</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Set your filters</span><br>
<span style="font-size:12px;color:#57534E">Enter keywords, role categories, locations, or employer names. Leave everything blank to pull the general public feed.</span>
</td>
<td style="padding:16px 14px;width:33%;background:#F0FDFA;border:1px solid #99F6E4;border-left:none;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#0F766E;letter-spacing:1px">STEP 2</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Run the Actor</span><br>
<span style="font-size:12px;color:#57534E">It reads Handshake's public listing and detail pages and normalizes each job into one clean record.</span>
</td>
<td style="padding:16px 14px;width:33%;background:#F0FDFA;border:1px solid #99F6E4;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#0F766E;letter-spacing:1px">STEP 3</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Export your data</span><br>
<span style="font-size:12px;color:#57534E">Download JSON, CSV, or Excel, or connect the dataset to your own dashboard or spreadsheet.</span>
</td>
</tr>
</table>

1. Open the Actor's **Input** tab and enter your keywords, role categories, or locations. All fields are optional.
2. Narrow results with employer name, employment type, workplace status, posting date, or compensation range if you need a tighter list.
3. Click **Start** and let the Actor run. Results stream into the dataset as they're found.
4. Open the **Output** tab to browse, filter, or download results in JSON, CSV, Excel, HTML, or XML.
5. Schedule the Actor to run daily or weekly to keep a running feed of new Handshake postings.

### 📝 Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `keywords` | array of strings | No | Free-text keywords matched against the job title and description. Leave empty to browse without a keyword filter. |
| `roles` | array of strings | No | Handshake role-category slugs, such as `accounting` or `software-engineering`. Up to 10 roles are queried per run. |
| `locations` | array of strings | No | City-state slugs, such as `new-york-ny` or `austin-tx`, or `remote`. Up to 10 locations are queried per run. |
| `employerNames` | array of strings | No | Keep only jobs whose employer name contains one of these strings. Matching ignores case. |
| `employmentTypes` | enum | No | Keep only listings matching the selected employment types (full time, part time, internship, temporary, contractor, or volunteer). Only applies to jobs where the source page publishes a type. |
| `workplaceTypes` | enum | No | Keep only listings matching the selected workplace status (remote or on site). Only jobs with a source-confirmed status are labeled; leave empty to keep all, including unlabeled. |
| `datePostedAfter` | string | No | Optional date. Keep jobs first posted on or after this date. |
| `datePostedBefore` | string | No | Optional date. Keep jobs first posted on or before this date. |
| `minCompensation` | integer | No | Keep only jobs whose published salary is at least this amount, in the listing's own pay-schedule unit. Jobs without a published salary are excluded once this is set. |
| `maxCompensation` | integer | No | Keep only jobs whose published salary is at most this amount. Leave at 0 for no upper bound. |
| `fetchJobDetails` | boolean | No | Visit each job's public detail page to add description, employment type, salary, and application deadline. Turn off for a faster, listing-only run. Defaults to true. |
| `maxItems` | integer | No | Maximum number of job listings to return across all searches. Defaults to 100. |
| `proxyConfiguration` | object | No | Proxy settings. Datacenter proxy is used by default and is enough for Handshake's public pages. Switch to residential only if you see blocking. |

### 📤 Output

Every run returns one record per job listing. Here's a real example:

```json
{
  "id": "9284157",
  "title": "Software Engineering Intern, Summer 2027",
  "employerName": "Northline Analytics",
  "employerLogoUrl": "https://static.joinhandshake.com/logos/northline-analytics.png",
  "city": "Austin",
  "state": "TX",
  "country": "United States",
  "locationLabel": "Austin, TX",
  "workplaceType": "on_site",
  "employmentType": "INTERNSHIP",
  "jobType": "Internship",
  "roleCategories": ["Software Engineering", "Data Science"],
  "salaryMin": 32,
  "salaryMax": 38,
  "paySchedule": "HOURLY",
  "currency": "USD",
  "description": "Join our platform team to build internal tools used by every engineer at Northline. You'll ship a real feature during your internship and pair with a senior engineer each week.",
  "datePosted": "2026-08-10T00:00:00.000Z",
  "applicationDeadline": "2026-10-01T23:59:00.000Z",
  "sourceUrl": "https://app.joinhandshake.com/public/jobs/9284157",
  "scrapedAt": "2026-08-23T09:12:44.000Z"
}
```

You can download the dataset in JSON, CSV, Excel, HTML, or XML directly from the Output tab, or pull it into your own tools through the Apify API.

### 📊 Data table

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Handshake's internal job ID. |
| `title` | string | Job or internship title. |
| `employerName` | string | Hiring company or organization name. |
| `employerLogoUrl` | string | Direct link to the employer's logo image, when published. |
| `city` | string | City where the role is based. |
| `state` | string | State where the role is based. |
| `country` | string | Country where the role is based. |
| `locationLabel` | string | Full location as displayed on Handshake. |
| `workplaceType` | string | Remote or on site, when the source page confirms it. |
| `employmentType` | string | Full time, part time, internship, temporary, contractor, or volunteer, when published. |
| `jobType` | string | Whether the listing is a job or an internship. |
| `roleCategories` | array of strings | Handshake role categories attached to the listing. |
| `salaryMin` | number | Minimum published salary, in the listing's own pay-schedule unit. |
| `salaryMax` | number | Maximum published salary, in the listing's own pay-schedule unit. |
| `paySchedule` | string | How the salary is measured, such as hourly, yearly, or per project. |
| `currency` | string | Currency of the published salary. |
| `description` | string | Full job description, when the detail page was fetched. |
| `datePosted` | string | Date the listing was first posted. |
| `applicationDeadline` | string | Date the listing stops accepting applications, when published. |
| `sourceUrl` | string | Direct link to apply on Handshake. |
| `scrapedAt` | string | Timestamp of when the record was collected. |

### 💰 Pricing

Pricing is pay per result and is billed per job record successfully saved to your dataset. Empty runs cost nothing.

There are no fixed monthly subscriptions, no maintenance fees, and no charge for filters that return zero matches. You only pay for the listings you actually get back.

### ⭐ Enjoying Handshake Jobs Scraper?

<table width="100%">
<tr>
<td style="padding:20px 24px 14px;background:#F0FDFA;border:1px solid #99F6E4;border-left:5px solid #0F766E;border-radius:10px 10px 0 0">
<span style="font-size:20px;letter-spacing:4px">⭐ ⭐ ⭐ ⭐ ⭐</span><br>
<span style="font-size:17px;font-weight:800;color:#1C1917">This feed just saved your team hours of manually checking Handshake for new postings.</span><br>
<span style="font-size:14px;color:#57534E">A 5-star rating takes 10 seconds and helps other campus recruiters and career-services teams find it. Your feedback also tells us what to build next.</span>
</td>
</tr>
<tr>
<td style="padding:0;background:#0F766E;border:1px solid #99F6E4;border-top:none;border-radius:0 0 10px 10px;text-align:center">
<a href="https://apify.com/getascraper/handshake-jobs-scraper/reviews" style="display:block;padding:13px 16px;color:#FFFFFF;text-decoration:none;font-weight:800;font-size:15px;letter-spacing:0.3px">★&nbsp;&nbsp;Rate this Actor on Apify</a>
</td>
</tr>
</table>

### 🛠️ Tips for better runs

- Turn off `fetchJobDetails` for a faster run when you only need title, employer, and location. Turn it on when you need salary, description, or deadline.
- Combine a role category with a location to narrow a broad feed without missing relevant postings.
- Set `datePostedAfter` and schedule the Actor daily to build a running feed of only new listings.
- Set `minCompensation` carefully. Jobs without a published salary are excluded once this filter is set, so a strict minimum will shrink your result count.

### ❓ FAQ

##### Does it get blocked?

No. The Actor reads only public Handshake pages that don't require a login, so there's nothing to block. Datacenter proxy, the default, is enough for reliable runs.

##### Do I need a Handshake account to use this?

No. Unlike scrapers that require Handshake credentials, this Actor never logs in and never asks for an account. It reads the same public pages any visitor can see.

##### How fresh is the data?

Every run reads the live Handshake pages at the moment it runs. Nothing is cached or reused from a previous run, so results reflect what's posted right now.

##### Are all job categories and locations supported?

Yes. Any Handshake role category or location slug works as a filter. Leave both empty to pull the general public feed without a role or location filter.

### 🔗 Other actors

- [Ashby Jobs Scraper: Hiring Change Monitor](https://apify.com/getascraper/ashby-jobs-monitor) ↗ - Monitors public Ashby job boards for new, updated, and closed roles.
- [Lever jobs scraper](https://apify.com/getascraper/lever-jobs-monitor) ↗ - Turns public Lever company boards into a hiring change feed.
- [SmartRecruiters jobs scraper](https://apify.com/getascraper/smartrecruiters-jobs-monitor) ↗ - Monitors public SmartRecruiters boards for new and updated postings.
- [Instahyre Jobs Scraper: India tech jobs & hiring monitor](https://apify.com/getascraper/instahyre-jobs-scraper) ↗ - Turns Instahyre listings into a dependable India tech hiring feed.
- [HIJOBS Scraper: Scotland's Highlands & Islands Jobs](https://apify.com/getascraper/hijobs-scraper) ↗ - Pulls every live HIJOBS vacancy from Scotland's Highlands and Islands.

# Actor input Schema

## `keywords` (type: `array`):

Optional free-text keywords matched against job title and description (case-insensitive). Leave empty to browse without a keyword filter.

## `roles` (type: `array`):

Handshake role-category slugs (e.g. "accounting", "software-engineering"). Each maps to a public /find-jobs/role/<slug>/ page. Up to 10 roles are queried.

## `locations` (type: `array`):

City-state slugs (e.g. "new-york-ny", "austin-tx") or "remote". Each maps to a public /find-jobs/<location>/ page. Up to 10 locations are queried.

## `employerNames` (type: `array`):

Keep only jobs whose employer name contains one of these strings (case-insensitive).

## `employmentTypes` (type: `array`):

Keep only listings matching these employment types. Type is only known for jobs where the source page publishes it (JSON-LD employmentType); leave empty to keep all types.

## `workplaceTypes` (type: `array`):

Keep only listings matching this workplace status. Only jobs with a source-confirmed remote/on-site flag are labeled; leave empty to keep all (including unlabeled).

## `datePostedAfter` (type: `string`):

Optional ISO date. Keep jobs first posted on or after this date.

## `datePostedBefore` (type: `string`):

Optional ISO date. Keep jobs first posted on or before this date.

## `minCompensation` (type: `integer`):

Keep only jobs whose published salary (in its own pay-schedule unit, e.g. per hour or per year) is at least this amount. Jobs without a published salary are excluded when this is set.

## `maxCompensation` (type: `integer`):

Keep only jobs whose published salary is at most this amount. Leave at 0 for no upper bound.

## `fetchJobDetails` (type: `boolean`):

Visit each job's public detail page to add description, employment type, salary, and application deadline. Uses one extra request per job. Turn off for a faster, lighter-weight listing-only run.

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

Maximum number of job listings to return across all searches.

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

Datacenter proxy is used by default and is sufficient for Handshake's public pages. Only switch to residential if you see blocking.

## Actor input object example

```json
{
  "keywords": [],
  "roles": [],
  "locations": [],
  "employerNames": [],
  "employmentTypes": [],
  "workplaceTypes": [],
  "datePostedAfter": "",
  "datePostedBefore": "",
  "minCompensation": 0,
  "maxCompensation": 0,
  "fetchJobDetails": true,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

No description

## `runSummary` (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 = {
    "keywords": [],
    "roles": [],
    "locations": [],
    "employerNames": [],
    "employmentTypes": [],
    "workplaceTypes": [],
    "datePostedAfter": "",
    "datePostedBefore": "",
    "minCompensation": 0,
    "maxCompensation": 0,
    "fetchJobDetails": true,
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("getascraper/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 = {
    "keywords": [],
    "roles": [],
    "locations": [],
    "employerNames": [],
    "employmentTypes": [],
    "workplaceTypes": [],
    "datePostedAfter": "",
    "datePostedBefore": "",
    "minCompensation": 0,
    "maxCompensation": 0,
    "fetchJobDetails": True,
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("getascraper/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 '{
  "keywords": [],
  "roles": [],
  "locations": [],
  "employerNames": [],
  "employmentTypes": [],
  "workplaceTypes": [],
  "datePostedAfter": "",
  "datePostedBefore": "",
  "minCompensation": 0,
  "maxCompensation": 0,
  "fetchJobDetails": true,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call getascraper/handshake-jobs-scraper --silent --output-dataset

```

## MCP server setup

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