# HigherEdJobs Scraper \[$1.4/1K💰] | Academic Jobs | Faculty Data (`ahmed_jasarevic/higheredjobs-scraper`) Actor

Extract faculty, administrative and executive job postings from HigherEdJobs.com — titles, institutions, locations, salaries, categories, deadlines, descriptions and apply links. Built for academic job-market research, salary benchmarking and higher-ed hiring intelligence. $1.40 per 1,000 jobs.

- **URL**: https://apify.com/ahmed_jasarevic/higheredjobs-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.30 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## HigherEdJobs Scraper

Extract faculty, administrative and executive job postings from **[HigherEdJobs.com](https://www.higheredjobs.com)** — job titles, hiring institutions, locations, published salaries, categories, application deadlines, full descriptions and direct apply links — in structured JSON.

Built for academic job-market research, faculty salary benchmarking, higher-education hiring intelligence and university-career-data pipelines.

### Track Faculty and Executive Hiring Across US Higher Education

- **Academic job-market research** — faculty, administrative and executive openings across US colleges and universities in one dataset.
- **Salary benchmarking** — capture published salary text (`salaryText`) wherever institutions disclose it.
- **Institution-level hiring intelligence** — which universities hire, for which disciplines, in which states, on what timeline.
- **Job-aggregation feeds** — normalized rows (title, institution, location, categories, apply URL) ready for boards or AI matching.
- **Deadline & pipeline monitoring** — application deadlines (`validThrough`) and posted dates for time-sensitive tracking.
- **Discipline-level analysis** — structured categories (Physics, Computer Science, Nursing …) for field-by-field comparisons.

### How It Works

![How the HigherEdJobs Scraper works: academic job pages become rows with institutions, salaries, deadlines, descriptions and apply links.](https://api.apify.com/v2/key-value-stores/oeuA0kLOyhbRM4fzt/records/how-it-works-higheredjobs-scraper)

The Actor parses the JSON-LD JobPosting block on each server-rendered page, then fills gaps from the HTML for salary, categories and application URLs. Incapsula challenges are detected and retried through fresh sessions or IPs.

Each row covers one job with its JobCode, title, institution, location, position type, categories, published salary text, posted date, deadline, description and apply link. Results are deduplicated by JobCode and stop exactly at maxItems.

HigherEdJobs is server-rendered, so a CheerioCrawler (plain HTTP + HTML parsing) is enough — no browser automation. Per page the Actor:

1. Parses the embedded **JSON-LD `JobPosting`** structured data (dates, description, organization, employment type).
2. Falls back to the **HTML markup** for fields JSON-LD does not expose (salary, categories, apply URL) and for VIP-branded page layouts.
3. Detects anti-bot challenge pages (Imperva Incapsula challenges datacenter IPs) and retries them with a fresh session or IP instead of saving empty data — the default proxy group is **UNBLOCKER**, which solves those challenges.
4. Deduplicates job detail pages by JobCode, follows pagination with `NumJobs=100` enforced, and counts saved results internally so `maxItems` is honored exactly — the crawl stops early instead of wasting requests. `robots.txt` is respected.

### Input Parameters

| Field | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `startUrls` | array | No | Today's jobs, 100/page | Search results, category/region listings, or individual detail pages. |
| `maxItems` | integer | No | `10` | Max saved job results; the crawl stops as soon as it is reached. |
| `maxRequestsPerCrawl` | integer | No | `200` | Page budget; each job detail costs one request. |
| `includeDetails` | boolean | No | `true` | Visit each job's detail page for description, apply URL, deadline and salary. `false` = fast listing-only crawl (billed per detail saved). |
| `maxConcurrency` | integer | No | `25` | Pages downloaded in parallel. Applied from the first request, so detail pages are fetched in parallel right away (10–50 recommended). |
| `proxy` | object | No | Apify Proxy, **UNBLOCKER** group | The site challenges datacenter IPs; UNBLOCKER solves it, RESIDENTIAL works as an alternative. |

Example start URLs:

```
https://www.higheredjobs.com/search/today.cfm?NumJobs=100
https://www.higheredjobs.com/search/advanced_action.cfm?Keyword=professor&NumJobs=100
https://www.higheredjobs.com/region/default.cfm?Region=5
https://www.higheredjobs.com/search/details.cfm?JobCode=179588781
```

### Output Fields

One object per job (15 fields):

| Field | Description |
| --- | --- |
| `jobId` | HigherEdJobs JobCode identifier |
| `title` | Job title |
| `institution`, `institutionUrl` | Hiring institution and its website |
| `location`, `city`, `state` | Job location |
| `positionType` | Full-Time, Part-Time, Contract, … |
| `categories` | Job categories (e.g. Physics, Computer Science) |
| `salaryText` | Salary as published, when provided |
| `postedDate` | Posting date (ISO from JSON-LD when available) |
| `deadline` | Application deadline (`validThrough`), when published |
| `description` | Full job description as plain text (detail mode) |
| `applyUrl` | Direct application link to the employer's site |
| `url` | HigherEdJobs detail page |

### Example Input

```json
{
  "startUrls": [{ "url": "https://www.higheredjobs.com/search/advanced_action.cfm?Keyword=computer+science&NumJobs=100" }],
  "maxItems": 200,
  "includeDetails": true,
  "maxRequestsPerCrawl": 250
}
```

### Example Output

```json
{
  "jobId": "179588781",
  "title": "Assistant Professor of Physics - Applied Mechanics",
  "institution": "California State University, San Marcos",
  "institutionUrl": "http://www.csusm.edu/",
  "location": "San Marcos, CA",
  "city": "San Marcos",
  "state": "CA",
  "positionType": "Full-Time",
  "categories": ["Physics"],
  "salaryText": "$6,221 - $13,224 per month",
  "postedDate": "2026-10-15T05:12:41.11",
  "deadline": "2028-04-07T23:59:59.9",
  "description": "California State University San Marcos has an opening for a tenure track assistant professor of physics…",
  "applyUrl": "https://apptrkr.com/9899433",
  "url": "https://www.higheredjobs.com/search/details.cfm?JobCode=179588781"
}
```

### Automate Academic Job Monitoring With Schedules & Webhooks

- **Schedule** daily runs on Today's Jobs or per-discipline searches to keep a rolling academic job-market dataset.
- **Webhooks** fire on run completion — push new postings into Slack, Sheets, a data warehouse or your own board.
- **API / MCP** — start runs and download datasets from any pipeline or AI agent.
- **Listing-only mode** (`includeDetails: false`) gives a cheap daily inventory of titles, institutions, locations and salaries; turn details on for full records.
- **Cost control** — free accounts get a capped preview; paid accounts are billed `$1.40` per 1,000 saved jobs plus `$2.00` per 1,000 detail fetches.

### Related Actors

Verified related actors on Apify that pair well with this one. All links point to real, publicly available actors.

- [Greenhouse, Lever & Ashby Job Scraper API | $1.50/1K](https://apify.com/bovi/greenhouse-lever-ashby-job-scraper)
- [Greenhouse, Lever & Ashby Jobs Scraper — with Salaries](https://apify.com/viridian_layout_ea2/company-career-site-jobs)
- [Greenhouse, Lever & Ashby Jobs Scraper — Salaries, No Login](https://apify.com/yugenox/ats-jobs-search)
- [HigherEdJobs Scraper: Academic Jobs, Salaries, and Monitoring](https://apify.com/getascraper/higheredjobs-com-scraper)
- [HigherEdJobs.com Scraper](https://apify.com/lexis-solutions/higheredjobs-com-scraper)

### Frequently Asked Questions

#### Does HigherEdJobs have an official API?

No public job-data API is published. HigherEdJobs serves server-rendered HTML search and detail pages (plus RSS feeds for categories, which open-source academic-job trackers use). Institutions post their ads through paid placement, not through a public developer API. This Actor reads the same public pages any visitor sees and returns them as structured JSON.

#### What are alternatives to HigherEdJobs for academic job data?

Comparable US higher-ed job boards: **The Chronicle of Higher Education** jobs (jobs.chronicle.com), **Inside Higher Ed** Careers (which offers employer-side posting automation but no public read API) and **HERC** (hercjobs.org, 550+ member institutions). For employer-direct feeds, many universities also publish through Greenhouse or Lever, whose public APIs (and the scrapers in Related Actors) cover them. Most serious academic-job trackers aggregate several boards at once.

#### Is salary data included?

Wherever an institution publishes a salary, the Actor captures the exact published text in `salaryText` (e.g. `$6,221 - $13,224 per month`). Many academic postings do not disclose salary — those rows carry an empty value rather than an estimate.

#### Can I monitor only new or changed postings?

This Actor returns the current state of each run's scope. For change-only feeds (NEW / UPDATED / EXPIRED events between scheduled runs), pair it with the monitoring-enabled HigherEdJobs actor linked in Related Actors, or diff consecutive datasets yourself — `jobId` is stable across runs.

#### How much does a run cost?

Pay per event: **$1.40 per 1,000 saved jobs** plus **$2.00 per 1,000 detail-page fetches** when `includeDetails` is on. 100 jobs with details cost 100 × ($0.0014 + $0.002) = **$0.34**. `includeDetails: false` drops the detail charge entirely for listing-only snapshots.

#### Can an AI agent call this Actor?

Yes — JSON input through the Apify API and MCP server. See [For AI Agents & LLM Apps](#for-ai-agents--llm-apps) for the minimal call, output fields and billing rules.

#### Why does the default proxy use the UNBLOCKER group?

HigherEdJobs runs Imperva Incapsula, which challenges datacenter IP addresses immediately. The default `proxy` input is Apify Proxy with the **UNBLOCKER** group, which solves those challenges automatically; RESIDENTIAL is a working alternative. Set `useApifyProxy: false` only for small crawls from a residential IP.

### For AI Agents & LLM Apps

Returns structured academic job postings from HigherEdJobs.com: institution, location, position type, categories, published salary, deadlines, description and apply link.

Minimal input (today's jobs, 100 saved):

```json
{ "maxItems": 100 }
```

Keyword search with details:

```json
{
  "startUrls": [{ "url": "https://www.higheredjobs.com/search/advanced_action.cfm?Keyword=professor&NumJobs=100" }],
  "maxItems": 250,
  "includeDetails": true
}
```

Output fields: `jobId`, `title`, `institution`, `institutionUrl`, `location`, `city`, `state`, `positionType`, `categories`, `salaryText`, `postedDate`, `deadline`, `description`, `applyUrl`, `url`.

Behaviors an agent should know:

- Omitted `startUrls` defaults to Today's jobs at 100 per page.
- `includeDetails: true` (default) adds one billed `job-detail` event ($2/1K) per saved job; `false` returns listing-only fields (no `description`, `applyUrl` or `deadline`).
- `maxItems` is enforced exactly via an internal counter — the run stops early once reached.
- Results are deduplicated by `jobId` (JobCode) even when multiple search pages link to the same job.
- Pagination links are rewritten with `NumJobs=100` so each listing page yields up to 100 jobs.
- Leave `proxy` at its default (UNBLOCKER) unless you have residential IPs; the site challenges datacenter addresses.

Billing: pay per event — `$0.0014` per saved job (`apify-default-dataset-item`) plus `$0.002` per detail page fetched (`job-detail`).

### Legal & Compliance Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by HigherEdJobs, Inc. or higheredjobs.com. It accesses only publicly available search and detail pages — no login, no authenticated areas; anti-bot challenge pages are retried through Apify's standard proxy products rather than by breaking into protected areas, and the Actor respects `robots.txt`. Job data returned (institutions, titles, locations, published salaries, descriptions) is what each institution already publishes to every visitor; where personal contact data appears inside descriptions, handle it under GDPR/CCPA rules. You are responsible for your own compliance with HigherEdJobs' Terms of Service and applicable data-protection law; do not use contact data from the output for unsolicited commercial outreach in violation of applicable law such as CAN-SPAM, GDPR or TCPA.

### SEO Keywords

higheredjobs scraper, higheredjobs api, higheredjobs data, academic job listings, higher education jobs data, faculty job postings, university job board data, higher ed job market, academic job market data, college job listings, faculty salary data, higher education hiring, scrape academic jobs, academic positions database, inside higher ed jobs, chronicle higher education jobs, herc jobs data, job data universities

# Actor input Schema

## `startUrls` (type: `array`):

HigherEdJobs pages to crawl - search results, category/region listings, or individual job detail pages. The default URL lists today's jobs, 100 per page. For a keyword search use e.g. https://www.higheredjobs.com/search/advanced_action.cfm?Keyword=professor\&NumJobs=100

## `maxRequestsPerCrawl` (type: `integer`):

Maximum number of pages (listing + detail) the crawler may load. Every job detail page costs one request, so raise this when crawling many jobs.

## `includeDetails` (type: `boolean`):

When enabled, each job listing is followed to its detail page to capture the full description, apply URL, deadline, and salary. Disable for a much faster listing-only crawl with the basic fields.

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

Maximum number of job results to save to the dataset. If not set, no limit is applied.

## `maxConcurrency` (type: `integer`):

Number of pages downloaded in parallel. The crawler runs at this concurrency from the first request instead of slowly ramping up. Values between 10 and 50 are recommended for this site; lower it if you encounter errors or rate limiting.

## `proxy` (type: `object`):

Proxy setup for the crawler. HigherEdJobs challenges datacenter IP addresses with an anti-bot page, so the default is Apify Proxy with the UNBLOCKER group. Set useApifyProxy to false to connect directly (only works from residential IPs).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.higheredjobs.com/search/today.cfm?NumJobs=100"
    }
  ],
  "maxRequestsPerCrawl": 200,
  "includeDetails": true,
  "maxItems": 10,
  "maxConcurrency": 25,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        {
            "url": "https://www.higheredjobs.com/search/today.cfm?NumJobs=100"
        }
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/higheredjobs-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 = {
    "startUrls": [{ "url": "https://www.higheredjobs.com/search/today.cfm?NumJobs=100" }],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/higheredjobs-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 '{
  "startUrls": [
    {
      "url": "https://www.higheredjobs.com/search/today.cfm?NumJobs=100"
    }
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}' |
apify call ahmed_jasarevic/higheredjobs-scraper --silent --output-dataset

```

## MCP server setup

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