All platforms

JobScore Jobs API.

Pull every open role from a company's JobScore board in a single unauthenticated request — the public JSON feed returns full descriptions, departments, experience levels, and remote status with no pagination to manage.

Get API access
JobScore
Live
30K+jobs indexed monthly
<3haverage discovery time
1hrefresh interval
Companies using JobScore
imgixMAQ SoftwareHexagon Mining
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 JobScore.

Data fields
  • Full HTML Job Descriptions
  • Department & Team Labels
  • Experience Level Tags
  • Remote Work Status
  • City, State & Country
  • Apply & Detail URLs
Use cases
  1. 01SMB Job Monitoring
  2. 02Careers Page Extraction
  3. 03Remote Role Aggregation
  4. 04Recruiting Market Research
Trusted by
imgixMAQ SoftwareHexagon Mining
DIY GUIDE

How to scrape JobScore.

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

RESTbeginnerNo published limits; the scraper spaces requests ~200ms apart at single concurrencyNo auth

Fetch the JSON feed for a company

Hit the public feed.json endpoint to retrieve every active job for a company in one request. No authentication or API key is required.

Step 1: Fetch the JSON feed for a company
import requests

company_code = "imgix"
url = f"https://careers.jobscore.com/jobs/{company_code}/feed.json"

response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()

company_name = data.get("company_name")
jobs = data.get("jobs", [])
print(f"Found {len(jobs)} jobs for {company_name}")

Parse job details from the response

Each job object already carries the full record — title, description, location, department, experience level, and apply URL — so no per-job detail request is needed. Extract the fields you care about.

Step 2: Parse job details from the response
for job in jobs:
    job_info = {
        "id": job.get("id"),
        "title": job.get("title"),
        "department": job.get("department"),
        "location": job.get("location"),
        "city": job.get("city"),
        "state": job.get("state"),
        "country": job.get("country"),
        "experience_level": job.get("experience_level"),
        "job_type": job.get("job_type"),
        "remote": job.get("remote"),
        "apply_url": job.get("apply_url"),
        "detail_url": job.get("detail_url"),
        "opened_date": job.get("opened_date"),
        "last_updated": job.get("last_updated_date"),
    }
    print(job_info)

Detect remote positions

The remote field is descriptive free text (e.g. "Yes | Can telecommute / work remotely 100% of the time") rather than a boolean, and location may simply read "Remote". Check both to flag remote roles reliably.

Step 3: Detect remote positions
def is_remote(job: dict) -> bool:
    remote_field = (job.get("remote") or "").lower()
    location = (job.get("location") or "").lower()

    # The remote field is free text, not a boolean
    if "yes" in remote_field or "100%" in remote_field or "remote" in remote_field:
        return True

    # Some boards flag remote purely via the location field
    if location == "remote":
        return True

    return False

remote_jobs = [j for j in jobs if is_remote(j)]
print(f"Found {len(remote_jobs)} remote positions")

Extract the company code from URLs

When discovering boards, pull the company code from any JobScore URL. The same code appears in both the /careers/ board path and the /jobs/ feed path, so one pattern handles both.

Step 4: Extract the company code from URLs
import re

def extract_company_code(url: str) -> str | None:
    """Extract the company code from a JobScore careers or feed URL."""
    pattern = r'careers.jobscore.com/(?:careers|jobs)/([^/?#]+)'
    match = re.search(pattern, url)
    return match.group(1) if match else None

# Example usage
urls = [
    "https://careers.jobscore.com/careers/imgix",
    "https://careers.jobscore.com/jobs/imgix/feed.json",
]

for url in urls:
    code = extract_company_code(url)
    print(f"URL: {url} -> Company Code: {code}")

Handle errors and empty boards

Map status codes to intent: a 404 means an invalid or closed board, while 403 and 429 mean you are being blocked or rate limited. An empty jobs array is a normal state for a company with no openings.

Step 5: Handle errors and empty boards
import requests

def fetch_jobscore_jobs(company_code: str) -> list[dict]:
    url = f"https://careers.jobscore.com/jobs/{company_code}/feed.json"

    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        data = response.json()
        return data.get("jobs", [])
    except requests.HTTPError as e:
        status = e.response.status_code
        if status == 404:
            print(f"Company '{company_code}' not found or board closed")
        elif status in (403, 429):
            print(f"Blocked or rate limited for '{company_code}' (HTTP {status})")
        else:
            print(f"HTTP error: {e}")
        return []
    except requests.RequestException as e:
        print(f"Request failed: {e}")
        return []

jobs = fetch_jobscore_jobs("imgix")
print(f"Retrieved {len(jobs)} jobs")
Common issues
mediumCompany code not found (404 error)

Confirm the company code against the live careers-page URL. A 404 means the board was closed or the company moved to a different ATS — treat it as not-found rather than retrying.

mediumBlocked or rate limited (403 / 429)

A 403 or 429 signals blocking or throttling, not a missing board. Back off and retry with a delay; keep requests spaced out and at low concurrency when scraping many companies.

highHTML error page returned instead of JSON

Always request feed.json (not feed) and confirm the response parses as JSON before use. A misconfigured or closed board can return an HTML page, which will break a naive json() call.

lowEmpty jobs array returned

This is the normal state for a company with no open positions. Treat an empty jobs array as a valid result, not an error condition.

lowjob_type field holds multiple values

The job_type field can contain a comma-separated list such as 'Contract, Temp to Full Time'. Split on commas and trim each value rather than storing it as a single label.

lowremote field is free text, not a boolean

Do not treat remote as a true/false flag. It is a descriptive string, and some boards signal remote only through the location field, so check both when classifying remote roles.

Best practices
  1. 1Prefer the feed.json API over HTML scraping for reliable, structured data
  2. 2Extract the company code from a careers-page URL before building the API call
  3. 3Space requests ~200ms apart at low concurrency when scraping many boards
  4. 4Cache results to avoid re-fetching the full board on every request
  5. 5Treat an empty jobs array as a valid response, not an error
  6. 6Check both the remote and location fields to classify remote roles
Or skip the complexity

One endpoint. All JobScore jobs. No scraping, no sessions, no maintenance.

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

Access JobScore
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