Radancy / TalentBrew Jobs API.
Extract clean, structured jobs from the enterprise career sites Radancy (TalentBrew) hosts for global employers, complete with JSON-LD descriptions, locations, and direct apply URLs.
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 Radancy / TalentBrew.
- Full Job Descriptions
- Structured Locations (JSON-LD)
- Employment Type & Category
- Posted & Closing Dates
- Direct Apply URLs
- Hiring Organization
- 01Enterprise employer monitoring
- 02Global careers-site aggregation
- 03Employer brand & hiring trends
- 04Apply-URL harvesting
How to scrape Radancy / TalentBrew.
Step-by-step guide to extracting jobs from Radancy / TalentBrew-powered career pages—endpoints, authentication, and working code.
import re
# The company ID is copied from the /job/ route and must match the board you target.
BOARDS = {
"careers.ba.com": {"company_id": "22348", "listing_path": "/search-jobs/"},
"careers.adeccogroup.com": {"company_id": "37746", "listing_path": "/en/search-jobs/"},
"www.att.jobs": {"company_id": "117", "listing_path": "/search-jobs/"},
}
# Optional 2-letter locale, then /job/<segments>/<companyId>/<postingId>
JOB_ROUTE = re.compile(r"/(?:[a-z]{2}/)?job/(?:[^/?#]+/)+(\d+)/(\d+)/?$", re.IGNORECASE)import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
def parse_listings(company_id: str, page_url: str):
html = requests.get(page_url, timeout=20).text
soup = BeautifulSoup(html, "html.parser")
root = soup.select_one("#search-results")
if root is None:
raise ValueError("Radancy page omitted #search-results")
jobs, seen = [], set()
for a in root.select("a[href*='/job/']"):
job_url = urljoin(page_url, a.get("href", "")).rstrip("/")
m = JOB_ROUTE.search(job_url)
if not m or m.group(1) != company_id:
continue # reject wrong-company / lookalike routes
posting_id = m.group(2)
if posting_id in seen:
continue
seen.add(posting_id)
row = a.find_parent("li") or a.parent
title_el = row.select_one("h2, h3, .job-title") if row else None
loc_el = row.select_one("[class*='location']") if row else None
jobs.append({
"external_id": posting_id,
"company_id": company_id,
"title": title_el.get_text(strip=True) if title_el else a.get_text(strip=True),
"listing_url": job_url,
"location": loc_el.get_text(strip=True) if loc_el else None,
})
return soup, root, jobsdef scrape_board(host: str, max_pages: int = 200):
cfg = BOARDS[host]
url = f"https://{host}{cfg['listing_path']}"
all_jobs, pages = [], 0
while url and pages < max_pages:
soup, root, jobs = parse_listings(cfg["company_id"], url)
all_jobs.extend(jobs)
pages += 1
total = root.get("data-total-job-results")
if total is not None and len(all_jobs) >= int(total):
break # authoritative total reached
nxt = soup.select_one(".pagination a.next[href]")
url = urljoin(url, nxt["href"]) if nxt else None # stop when no next link
return all_jobsimport json
def fetch_details(job: dict):
html = requests.get(job["listing_url"], timeout=20).text
soup = BeautifulSoup(html, "html.parser")
posting = None
for script in soup.select("script[type='application/ld+json']"):
if "JobPosting" in script.text:
posting = json.loads(script.text)
break
if posting is None:
raise ValueError("Radancy detail omitted JobPosting JSON-LD")
meta = soup.select_one("meta[name='search-job-apply-url']")
apply_url = meta["content"] if meta and meta.get("content") else job["listing_url"]
return {
"external_id": job["external_id"],
"title": posting.get("title", job["title"]),
"description": posting.get("description"), # HTML — strip before storing
"employment_type": posting.get("employmentType"),
"hiring_organization": (posting.get("hiringOrganization") or {}).get("name"),
"locations": posting.get("jobLocation"), # list of address structs
"posted_at": posting.get("datePosted"),
"closes_at": posting.get("validThrough"),
"apply_url": apply_url,
}Radancy only resolves for a known host paired with its numeric company ID; a Radancy-like path on another domain, or the wrong company ID, is rejected. Open a live posting, read the /job/.../{companyId}/{postingId} route, and register the exact host + ID before scraping.
TalentBrew advertises /search-jobs/results helpers, but they return HTML fragments, not a structured API. Parse the server-rendered #search-results markup instead of looking for a JSON endpoint.
There is no explicit last-page flag beyond data-total-job-results. Terminate when the .pagination a.next link is absent, and additionally stop once your collected count reaches data-total-job-results.
Some pages omit the JSON-LD block or serve malformed JSON. Guard the json.loads call, skip the posting when no JobPosting script is present, and retry later rather than failing the whole run.
These enterprise sites sit behind a WAF that watches request cadence. Keep concurrency low (around 3 detail fetches) and space requests ~100ms apart to stay under detection thresholds.
Deleted postings return 404 or 410 on the detail fetch. Treat those status codes as a removal signal and drop the job rather than retrying.
- 1Confirm the numeric company ID from a live /job/.../{companyId}/{postingId} URL before scraping a board.
- 2Parse the server-rendered #search-results HTML — do not rely on /search-jobs/results as a JSON API.
- 3Prefer JobPosting JSON-LD for authoritative title, description, locations, and dates.
- 4Read the real application URL from meta[name='search-job-apply-url'], falling back to the listing URL.
- 5Throttle to ~100ms between requests with low concurrency to stay under WAF thresholds.
- 6Terminate pagination on the absence of a next link and cross-check data-total-job-results.
One endpoint. All Radancy / TalentBrew jobs. No scraping, no sessions, no maintenance.
Get API accesscurl "https://connect.jobo.world/api/jobs?sources=radancy / talentbrew" \
-H "X-Api-Key: YOUR_KEY" Access Radancy / TalentBrew
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.