All platforms

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.

Get API access
Radancy / TalentBrew
Live
<3haverage discovery time
1hrefresh interval
Developer tools

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.

Data fields
  • Full Job Descriptions
  • Structured Locations (JSON-LD)
  • Employment Type & Category
  • Posted & Closing Dates
  • Direct Apply URLs
  • Hiring Organization
Use cases
  1. 01Enterprise employer monitoring
  2. 02Global careers-site aggregation
  3. 03Employer brand & hiring trends
  4. 04Apply-URL harvesting
DIY GUIDE

How to scrape Radancy / TalentBrew.

Step-by-step guide to extracting jobs from Radancy / TalentBrew-powered career pages—endpoints, authentication, and working code.

HTMLadvancedNo published limit; ~100ms between requests, 3 concurrent detail fetches (self-imposed)No auth

Identify the career-site host and company ID

Each Radancy / TalentBrew board is a company-specific host, and the numeric company ID is embedded verbatim in every /job/.../{companyId}/{postingId} route. Confirm the ID from a real posting URL before scraping — the same regex you use to read it also lets you reject lookalike routes.

Step 1: Identify the career-site host and company ID
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)

Fetch and parse the search-jobs listing page

There is no structured jobs API — the /search-jobs/ page is server-rendered HTML. Read the #search-results container, collect anchors pointing at /job/ routes, and keep only those whose route company ID matches the board (this drops adverts and cross-linked postings).

Step 2: Fetch and parse the search-jobs listing page
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, jobs

Follow pagination defensively

Walk pages via the .pagination a.next link and stop when it is absent. Cross-check the authoritative data-total-job-results count on #search-results so you terminate as soon as every posting is collected instead of guessing the last page.

Step 3: Follow pagination defensively
def 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_jobs

Read JobPosting JSON-LD and the apply URL from the detail page

Detail pages embed authoritative JobPosting JSON-LD with the title, HTML description, locations, and dates. The real application URL lives in meta[name='search-job-apply-url'] — it may point outside TalentBrew, so fall back to the listing URL when it is missing.

Step 4: Read JobPosting JSON-LD and the apply URL from the detail page
import 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,
    }
Common issues
highThe board host or company ID is not one you have mapped

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.

mediumExpecting a JSON jobs API from /search-jobs/results

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.

mediumPagination never clearly ends on large boards

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.

mediumDetail page has no JobPosting JSON-LD or it fails to parse

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.

mediumRequests get blocked or throttled by the WAF

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.

lowRemoved postings still appear in your listing set

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.

Best practices
  1. 1Confirm the numeric company ID from a live /job/.../{companyId}/{postingId} URL before scraping a board.
  2. 2Parse the server-rendered #search-results HTML — do not rely on /search-jobs/results as a JSON API.
  3. 3Prefer JobPosting JSON-LD for authoritative title, description, locations, and dates.
  4. 4Read the real application URL from meta[name='search-job-apply-url'], falling back to the listing URL.
  5. 5Throttle to ~100ms between requests with low concurrency to stay under WAF thresholds.
  6. 6Terminate pagination on the absence of a next link and cross-check data-total-job-results.
Or skip the complexity

One endpoint. All Radancy / TalentBrew jobs. No scraping, no sessions, no maintenance.

Get API access
cURL
curl "https://connect.jobo.world/api/jobs?sources=radancy / talentbrew" \
  -H "X-Api-Key: YOUR_KEY"
Ready to integrate

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.

99.9%API uptime
<200msAvg response
50M+Jobs processed