EdJoin.org Scraper icon

EdJoin.org Scraper

Scrape EdJoin.org K-12 and higher-ed jobs by keyword, location, filters or URL. Extract districts, locations, salaries, openings, deadlines,…

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

EdJoin.org Scraper at a glance

EdJoin.org Scraper is a ready-to-run Apify actor from abotapi for collecting jobs data. Its documented output includes id, url, title, job type and type id, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Jobs, Developer Tools, Automation
Pricing
$1.80 per 1,000 results (Free plan), from $1.00 on paid plans
Output
Documented below · JSON, CSV, Excel
Inputs
22 options

Scrape EdJoin.org K-12 and higher-ed jobs by keyword, location, filters or URL. Extract districts, locations, salaries, openings, deadlines, requirements and full descriptions, with optional contact and address details.

What EdJoin.org Scraper can do

  • Two ways in. Search by keyword, location and filters, or paste EdJoin search and job-posting links directly. No need to build query strings by hand.
  • One flat record per job. Every listing merges the search-result card and, optionally, its detail page into a single record: about 40 fields on a listing-only run, more once detail enrichment is on.
  • Full detail enrichment on demand. Contact name and email, complete street address, education and experience requirements, skills, the full job summary and description, employer logo and the offsite apply link, one extra request per job.
  • Filters that narrow the search at the source. Job type, category, online-application-only, posted-within-days and sort order are all applied server-side, not filtered out after the fact.
  • Walks a whole search, or an entire catalogue, forward automatically. Set a hard job or page cap, or let it run until results run out.
  • Built for monitoring. Incremental mode tracks a recurring search over time and classifies every job NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED, so a scheduled run bills only for what changed.

Choose what to collect

These inputs let you configure EdJoin.org Scraper - Education Jobs, Salaries & Districts. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestring · requiredsearch = enter keyword, location and filters. url = paste EdJoin search or job-posting URLs.

Choices: search, url

keywordsstringJob title, keyword or organization to search for, e.g. 'teacher', 'principal', 'speech pathologist'. Leave empty to list everything.
locationstringFree-text location to narrow the search, e.g. 'Los Angeles', 'San Diego', a county or a ZIP. Leave empty for statewide / all.
jobTypeIdsarrayRestrict to specific EdJoin job types by numeric ID (see the jobTypeId field in any output record). Example: 4 = Teacher - Middle Grades, 9 = Teacher - Special Education, 23 = Teacher Assistant / Aide. Multiple IDs are OR-combined.
categoryIdintegerRestrict to one EdJoin category by numeric ID (see categoryId in output). 1 = Certificated, 2 = Classified, 3 = Management, 4 = Other. Leave empty for all.
stateIdintegerRetired: the live source no longer honors a state filter (every value returns the unfiltered total), so this value is ignored. Saved tasks keep working.
onlineApplicationOnlybooleanON: only return jobs that accept an EdJoin online application. OFF / unset: include all jobs.
Show 15 more inputs
More input fields
InputWhat it controls
postedWithinDaysintegerOnly jobs posted within the last N days. 0 = no date limit.
urlsarrayEdJoin search URLs (/Home/Jobs?...) or job-posting URLs (/Home/JobPosting/, /Home/DistrictJobPosting/). Multi-URL supported. Also accepted under the name startUrls. Left untouched, url mode scrapes the 8 example URLs listed here (one distinct target each; the non-www host, legacy /Home/DistrictJobPosting/ and extra-query-string variants of a posting URL are also accepted but resolve to the same posting, so they are not listed).
sortBystringOrder of results. Newest first is the EdJoin default.

Choices: newest, oldest

fetchDetailsbooleanON: each job gets contact name + email, full street address, application deadline, length of work year, education + experience requirements, skills, job summary, full description, employer logo, offsite application link and attachment (one extra request per job). OFF: faster, listing-card fields only (still ~35 fields).
maxListingsintegerPrimary limit: overall cap on jobs across all searches/URLs. The run stops as soon as this many jobs are collected. Set to 0 for unlimited (then Max pages becomes the ceiling).
maxPagesinteger0 (default) means walk the whole catalogue for each search: pagination stops naturally once a page comes back empty or repeats jobs already collected, or sooner once Max jobs is reached. Set a number only if you want an explicit page cap below that natural stop.
resumeFromRunIdstringOptional. Paste a previous run ID or dataset ID to continue a large walk-all pull: jobs already saved by that run are loaded before scraping starts and skipped, so this run only appends new jobs. Leave empty for a normal fresh run. Distinct from Incremental mode below, which tracks a RECURRING search rather than replaying one run.
incrementalModebooleanON: remembers this search/URL set's results between scheduled runs and classifies each job as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED, so a recurring run only bills for what changed. OFF (default): every run is a plain fresh pull, same as today. Each job's fields are compared with its previous scrape (every output field except scrapedAt and any you list under 'Ignore fields when detecting changes'; detail-only fields are skipped on a run where the detail page did not load). Unrelated to 'Resume from a prior run' above (that continues one interrupted run; this tracks a recurring search).
stateKeystringOptional label for the incremental-mode baseline. Leave empty to derive it automatically from your search/URL settings (recommended). Set your own text only if you want to deliberately share one baseline across otherwise-different search settings, or split one search into several independently-tracked campaigns. Only applies when Incremental mode is ON.
emitUnchangedbooleanON: also return jobs that have not changed since the last run (changeType UNCHANGED), returns and BILLS extra rows every run. OFF (default): unchanged jobs are skipped; only NEW/UPDATED/REAPPEARED/EXPIRED are returned. Only applies when Incremental mode is ON.
emitExpiredbooleanON: also return a row for each previously-tracked job no longer found (changeType EXPIRED), returns and BILLS extra rows every run. Only emitted after a run that scanned the full tracked search, with no cap or resume in effect. OFF (default): expired jobs are not reported. Only applies when Incremental mode is ON.
ignoreFieldsForChangesarrayField names that must NOT count as a change when Incremental mode compares a job with its previous scrape (for example applicationDeadline or numberOpenings). Matches the name at any depth, or an exact dotted path. Ignored fields are still returned in the output; they only stop a job being flagged UPDATED. Leave empty to compare every field except scrapedAt. Only applies when Incremental mode is ON.
mcpConnectorsarrayOptionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON, the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).
notionParentPageUrlstringURL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.
maxNotifyListingsintegerCap on items written to each connector per run. Does not affect the dataset.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

idID
urlURL (link)
titleTitle
jobTypeJob type
jobTypeIdType ID
categoryNameCategory
districtNameDistrict
cityCity
countyNameCounty
stateNameState
locationLocation
salaryDisplaySalary
Show 30 more fields
salaryInfoAdd'l salary info
payRangeFromPay from
payRangeToPay to
payRangeUnitPay unit
employmentTypeEmployment
numberOpeningsOpenings
onlineAppOnline app
datePostedPosted
applicationDeadlineDeadline
workYearLengthWork year
contactNameContact
contactEmailContact email
streetAddressAddress
postalCodeZIP
employerUrlEmployer URL (link)
employerLogoLogo (link)
offsiteUrlApply URL (link)
districtdistrict
countycounty
contactcontact
datedate
statestate
searchQuerySearch
scrapedAtScraped
changeTypeChange type
changedFieldsChanged fields
firstSeenAtFirst seen
lastSeenAtLast seen
educationRequirementsEducation
experienceRequirementsExperience

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "id": 20000001,
  "url": "https://www.edjoin.org/Home/JobPosting/20000001",
  "title": "Elementary Teacher, 1.0 FTE, 2026-2027",
  "districtName": "Example Unified School District",
  "city": "Exampleton",
  "countyName": "Example",
  "countyFullName": "Example County, CA",
  "stateName": "California",
  "stateId": 24,
  "zip": "90000",
  "location": "Exampleton, California",
  "jobType": "Teacher - K-6",
  "jobTypeId": 48,
  "categoryName": "Certificated",
  "categoryId": 1,
  "salaryInfo": "See attached certificated salary schedule",
  "salaryDisplay": "$60,000 - $117,000 Annually",
  "payRangeFrom": "$60,000",
  "payRangeTo": "$117,000",
  "payRangeUnit": "Annually",
  "employmentType": "Full Time",
  "numberOpenings": 2,
  "onlineApp": true,
  "datePosted": "2026-01-01T00:00:00.000Z",
  "applicationDeadline": "2026-02-01T00:00:00.000Z",
  "workYearLength": "2026-2027 School Year",
  "contactName": "Jane Example",
  "contactEmail": "jobs@example.org",
  "streetAddress": "100 Example Blvd.",
  "addressLocality": "Exampleton",
  "addressRegion": "California",
  "postalCode": "90000-0000",
  "addressCountry": "US",
  "employerName": "Example Unified School District",
  "employerUrl": "https://www.edjoin.org/example",
  "employerLogo": "https://example.org/logos/example-000000.png",
  "educationRequirements": "Valid California Teaching Credential",
  "experienceRequirements": "Online application required; incomplete applications are screened out.",
  "skills": "BA/BS plus subject-matter competence",
  "jobSummary": "Full job summary text appears here when detail enrichment is on.",
  "description": "See attachment on original job posting",
  "offsiteUrl": "https://www.example.org/apply",
  "attachmentName": "Job-Description-00000000.pdf",
  "searchQuery": "teacher",
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}

Ways to use this data

  • School HR and staffing teams: track new certificated and classified openings across districts to prioritize sourcing and outreach.
  • Recruiting and HR-tech platforms: mirror EdJoin postings into your own job board or ATS without sending users to EdJoin directly.
  • Compensation and market-rate teams: collect posted salary ranges and requirements to benchmark against your own pay bands.
  • Education researchers and journalists: build a dataset of job postings, salary ranges and hiring activity across school districts over time.
  • Districts and agencies monitoring their own postings: schedule a recurring pull with Incremental mode to know the moment a listing changes or is taken down.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does EdJoin.org Scraper return?

The documented output for EdJoin.org Scraper includes id, url, title, job type, type id, category, district and city. Availability of each field depends on the source page and the selected mode.

How much does EdJoin.org Scraper cost?

It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Can I get only new or changed jobs on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated, reappeared or expired jobs for the same search, and unchanged ones are not billed unless you turn on Emit unchanged.

What's the difference between Resume and Incremental mode?

Resume from a prior run continues ONE interrupted walk-all pull using a pasted run or dataset ID: a one-time continuation that skips every job that run already saved (pair it with a search URL carrying &page=N, as described above, so the walk does not stop on already-saved first pages). Incremental mode remembers a search's baseline itself between scheduled runs, so a recurring run only returns what changed, with no ID to paste. They solve different problems and can be combined to seed Incremental mode's baseline from a prior resume pull.

Why did a resumed run, or my second search URL, return far fewer jobs than expected?

A search stops as soon as it reads a page holding only jobs the run has already seen, and that includes jobs from another search URL in the same run and jobs loaded from a resumed run. So a resumed walk-all pull can stop on page 1 with zero jobs, and a second search URL that overlaps the first can stop before its own new jobs. Run overlapping search URLs as separate runs, and resume a large pull through a search URL with &page=N as described under Resume and recurring updates above. A job-posting URL pasted next to searches can also be dropped if one of those searches skipped that job because of its share of Max jobs; paste posting URLs in their own run.

Why did my run fail instead of returning an empty dataset?

If EdJoin refuses every request a run makes, the run stops with a clear message so "no jobs match this search" is never confused with "nothing could be read." Run it again in a few minutes. A search that genuinely comes back empty still succeeds and returns a note instead of a job.

Ready to collect with EdJoin.org Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.