A lightweight Python client for job listings. No API key, no headless browser, no scraping service.
Project description
jobcore
A lightweight Python client for job listings. No API key, no browser automation.
Currently supports Apple career listings (jobs.apple.com). More sources planned.
Install
Available on PyPI:
pip install jobcore
Or install from source:
git clone https://github.com/Mikedan37/jobcore.git
cd jobcore
pip install -e .
Requires Python 3.10+ and httpx.
Quick example
from jobcore import JobCoreClient
client = JobCoreClient()
for job in client.search(query="iOS engineer", limit=5):
print(f"{job.title} — {job.team.name}")
print(f" {job.location} · {job.posting_date}")
print(f" {job.url}")
print()
client.close()
CLI
~6,000+ live positions across teams and locations.
jobcore count # total open positions
jobcore search "Swift" # search by keyword
jobcore search --team "Software" # filter by team
jobcore search "iOS" --location "US" # combine filters
jobcore page 5 # fetch a specific page
jobcore dump > jobs.jsonl # all jobs as JSON lines
Or via module: python -m jobcore count
Why this exists
Major employers don't always provide public job APIs.
This package gives you a clean, stable interface over public job listings so you can:
- search roles programmatically
- build job matching pipelines
- automate job discovery workflows
One dependency (httpx). No Selenium. No API key.
What this does
- Fetches job listings from public career pages
- Parses structured job data from server-rendered HTML (no headless browser)
- Returns typed Python models (
Job,JobCorePage) - Handles pagination, retries, and rate limiting
- Provides a small CLI for quick lookups and bulk export
What this does NOT do
- Does not apply to jobs on your behalf
- Does not bypass authentication or access controls
- Does not scrape aggressively or circumvent rate limits
- Does not enrich, score, or rank jobs
Responsible use
This library parses data already served to standard browser requests. Built-in safeguards:
- 0.5s default delay between page requests. Do not set it to zero.
- 3 retries max on transient failures. No infinite loops.
- Honest User-Agent with a project URL. Do not spoof it.
If a source changes their site structure or blocks automated access, this library will stop working. That is their right. File an issue and we will adapt.
API reference
JobCoreClient
client = JobCoreClient(delay=0.5, retries=3, timeout=30.0)
| Method | Returns | Description |
|---|---|---|
search(query=, location=, team=, limit=) |
list[Job] |
Search with client-side filtering |
search_page(page=1) |
JobCorePage |
Fetch a single page (20 jobs) |
iter_jobs(max_pages=300) |
Iterator[Job] |
Auto-paginate all jobs |
get_total_count() |
int |
Total open positions |
close() |
— | Close HTTP client |
Supports context manager: with JobCoreClient() as client: ...
Job
| Field | Type | Description |
|---|---|---|
position_id |
str |
Unique position ID |
title |
str |
Job title |
summary |
str |
2-3 paragraph description |
url |
str |
Direct link to posting |
posted_at |
datetime? |
UTC timestamp |
posting_date |
str |
Human-readable date |
team |
JobTeam |
Department (name, code) |
locations |
list[JobLocation] |
One or more locations |
home_office |
bool |
Remote-eligible |
weekly_hours |
int |
40 = full-time |
Properties: location (primary as string), is_remote, is_part_time
JobCorePage
| Field | Type | Description |
|---|---|---|
jobs |
list[Job] |
Up to 20 jobs |
total_records |
int |
Total matching jobs |
page |
int |
Current page (1-indexed) |
Properties: total_pages, has_next
Development
git clone https://github.com/Mikedan37/jobcore.git
cd jobcore
pip install -e ".[dev]"
pytest tests/ -v # 32 tests, ~0.5s, fully offline
Tests parse saved HTML fixtures. No network calls. If a source changes their site and tests break, re-capture the fixture and update the parser.
Limitations
- Client-side filtering. Source pages may not support server-side text queries.
search()fetches pages and filters locally. - Summaries only. The
summaryfield is from the search listing. Full detail pages are not fetched. - HTML parsing is inherently fragile. If a source redesigns their site, the parser will break. File an issue.
Maintained by
Maintained by Danylchuk Studios, LLC (Seeker project).
Unofficial job data tooling. Not affiliated with any company whose listings are accessed.
Intended for personal use, research, and tooling. Not for high-volume scraping or commercial redistribution of job listings.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jobcore-0.2.0.tar.gz.
File metadata
- Download URL: jobcore-0.2.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12a6a23ef0bbab107ce1c8ce8fcc212b0a9731eb7250de1b22cd24db205c1939
|
|
| MD5 |
c881783d873e0f37a9e5efdbb5acfba8
|
|
| BLAKE2b-256 |
5ace4d0332a0f0d040ae40e6ffe191ecf789494178e9802a6229fce646421a26
|
File details
Details for the file jobcore-0.2.0-py3-none-any.whl.
File metadata
- Download URL: jobcore-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2430016b3b99a186f03c863d11ddc8523a70c224068eddb03dcba8dcc2a3cb7b
|
|
| MD5 |
d066e8059790187e3f732658d37fb846
|
|
| BLAKE2b-256 |
e9d97e815f2a64430976cc39dae17dd01fb3d213c180ab33497140d64a459c44
|