JoblinkApply Jobs API.
Extract structured listings and JSON-LD-backed job detail from any numeric JoblinkApply tenant board — Jobo normalizes titles, locations, employment types, and apply links behind one unified API.
Try the API.
Test Jobs and Feed endpoints against https://connect.jobo.world with live request/response examples, then copy ready-to-use curl commands.
What's in every response.
Data fields, real-world applications, and the companies already running on JoblinkApply.
- Full Job Descriptions
- Structured Locations
- Employment Type
- Posted & Closing Dates
- Hiring Organization Name
- Canonical Apply URLs
- 01Local & Facilities Job Aggregation
- 02Employer Board Monitoring
- 03JSON-LD Detail Enrichment
- 04Apply-Link Syndication
How to scrape JoblinkApply.
Step-by-step guide to extracting jobs from JoblinkApply-powered career pages—endpoints, authentication, and working code.
import re
# JoblinkApply boards and jobs both live under /Joblink/{tenantId} (numeric).
def tenant_id_from_url(url: str) -> str:
match = re.search(r"/Joblink/(\d+)", url)
if not match:
raise ValueError(f"No numeric JoblinkApply tenant in URL: {url}")
return match.group(1)
tenant_id = tenant_id_from_url("https://www.joblinkapply.com/Joblink/6924")import requests
BASE = "https://www.joblinkapply.com"
HEADERS = {"User-Agent": "Mozilla/5.0 (compatible; JoboBot/1.0)"}
def fetch_listings_html(tenant_id: str) -> str:
url = (
f"{BASE}/Joblink/{tenant_id}"
"/Search/SearchWithFilters?WithinDistance=25&SortDirection=Descending"
)
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
return resp.textfrom bs4 import BeautifulSoup
JOB_PATH = re.compile(r"^/Joblink/(\d+)/Job/Index/(\d+)")
def parse_listings(html: str, tenant_id: str) -> list[dict]:
soup = BeautifulSoup(html, "html.parser")
jobs, seen = [], set()
for anchor in soup.select("tr a[href]"):
match = JOB_PATH.match(anchor.get("href", ""))
if not match:
continue
href_tenant, job_id = match.group(1), match.group(2)
# Defensive: only accept rows that belong to the requested tenant.
if href_tenant != tenant_id or job_id in seen:
continue
seen.add(job_id)
jobs.append({
"job_id": job_id,
"title": anchor.get_text(strip=True),
"detail_url": f"{BASE}/Joblink/{tenant_id}/Job/Index/{job_id}",
})
return jobsimport json
def fetch_job_detail(tenant_id: str, job_id: str) -> dict:
url = f"{BASE}/Joblink/{tenant_id}/Job/Index/{job_id}"
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
posting = None
for tag in soup.find_all("script", type="application/ld+json"):
try:
data = json.loads(tag.string or "")
except (json.JSONDecodeError, TypeError):
continue # unescaped quotes in description can break the block
for node in (data if isinstance(data, list) else [data]):
if isinstance(node, dict) and node.get("@type") == "JobPosting":
posting = node
break
posting = posting or {}
heading = soup.select_one("h1#JobTitle") or soup.select_one("h1")
title = posting.get("title") or (heading.get_text(strip=True) if heading else None)
description = posting.get("description")
if not description:
section = (soup.select_one("section[aria-label='Job Summary']")
or soup.select_one("#JobSeekerContentArea"))
description = section.get_text("\n", strip=True) if section else None
org = posting.get("hiringOrganization") or {}
return {
"job_id": job_id,
"title": title,
"description": description,
"company_name": org.get("name") if isinstance(org, dict) else None,
"employment_type": posting.get("employmentType"),
"date_posted": posting.get("datePosted"),
"valid_through": posting.get("validThrough"),
"apply_url": url,
}Wrap json.loads in a try/except and fall back to the visible section[aria-label='Job Summary'] (or #JobSeekerContentArea) for the description while still reading the other fields from JSON-LD.
Only accept rows whose /Joblink/{id}/Job/Index/{jobId} tenant equals the board you requested, and dedupe by numeric job ID.
Cap concurrency to ~3 detail fetches with roughly 500 ms between requests and back off when you see 403 or 429.
Validate that both IDs are digits before requesting, and treat a detail-page 404 as a removed job rather than a transient error to retry.
- 1Rebuild listing and detail URLs from the numeric tenant and job IDs rather than trusting persisted or anchor hrefs.
- 2Prefer JSON-LD JobPosting fields, but always keep the HTML Job Summary fallback for descriptions.
- 3Throttle to ~3 concurrent detail fetches with ~500 ms between requests to avoid 403/429.
- 4Parse posted and valid-through dates as US (en-US) format and store as UTC — the board exposes no tenant time zone.
- 5Dedupe jobs by numeric job ID and drop any row that belongs to another tenant.
- 6Send a browser-like User-Agent; boards serve server-rendered HTML and need no API key.
One endpoint. All JoblinkApply jobs. No scraping, no sessions, no maintenance.
Get API accesscurl "https://connect.jobo.world/api/jobs?sources=joblinkapply" \
-H "X-Api-Key: YOUR_KEY" Access JoblinkApply
job data today.
One API call. Structured data. No scraping infrastructure to build or maintain — start with the free tier and scale as you grow.