Recooty Jobs API.
Server-side rendered ATS platform for small businesses with HTML-based job boards and sitemap discovery support.
Try the API.
Test Jobs, Feed, and Auto-Apply 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 Recooty.
- SMB focus
- Simple interface
- HTML-based rendering
- Sitemap discovery
- JSON-LD structured data
- Two domain support
- 01SMB job monitoring
- 02Company discovery via sitemap
- 03HTML scraping workflows
- 04Structured data extraction
How to scrape Recooty.
Step-by-step guide to extracting jobs from Recooty-powered career pages—endpoints, authentication, and working code.
import requests
import xml.etree.ElementTree as ET
from urllib.parse import urlparse
def discover_companies_from_sitemap():
"""Extract unique company slugs from Recooty sitemap."""
sitemap_url = "https://jobs.recooty.com/sitemap.xml"
response = requests.get(sitemap_url, timeout=30)
response.raise_for_status()
root = ET.fromstring(response.content)
companies = set()
# Parse all URLs and extract company slugs
for url in root.findall('.//{http://www.sitemaps.org/schemas/sitemap/0.9}loc'):
path = urlparse(url.text).path
parts = path.strip('/').split('/')
if parts:
companies.add(parts[0])
print(f"Found {len(companies)} unique companies")
return list(companies)
companies = discover_companies_from_sitemap()import requests
from bs4 import BeautifulSoup
def fetch_listings_page(company_slug: str, page: int = 1):
"""Fetch the HTML listings page for a company."""
base_url = "https://careerspage.io"
url = f"{base_url}/{company_slug}"
if page > 1:
url = f"{url}?page={page}"
headers = {
"User-Agent": "Mozilla/5.0 (compatible; JobScraper/1.0)"
}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
return response.text
html = fetch_listings_page("recooty-inc")
print(f"Fetched {len(html)} bytes")from bs4 import BeautifulSoup
def parse_job_listings(html: str, company_slug: str):
"""Parse job listings from Recooty HTML."""
soup = BeautifulSoup(html, 'html.parser')
jobs = []
# Find all job card containers
job_cards = soup.select('div.pt-7.px-xl-9.bg-white.rounded')
for card in job_cards:
# Extract job title and URL
title_link = card.select_one('h3 a.font-size-6.heading-default-color')
if not title_link:
continue
title = title_link.get_text(strip=True)
href = title_link.get('href', '')
# Extract metadata from list items
list_items = card.select('ul.list-unstyled li span')
location = ""
employment_type = ""
experience = ""
for i, item in enumerate(list_items):
text = item.get_text(strip=True)
if i == 0:
location = text
elif i == 1:
employment_type = text
elif i == 2:
experience = text
# Build full URL
job_url = f"https://careerspage.io{href}" if href.startswith('/') else href
jobs.append({
'title': title,
'location': location,
'employment_type': employment_type,
'experience_level': experience,
'url': job_url,
})
return jobs
jobs = parse_job_listings(html, "recooty-inc")
print(f"Found {len(jobs)} jobs")import json
import requests
from bs4 import BeautifulSoup
def fetch_job_details(job_url: str):
"""Fetch and parse job details including JSON-LD structured data."""
response = requests.get(job_url, timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Extract JSON-LD structured data
json_ld_data = None
json_ld_script = soup.select_one('script[type="application/ld+json"]')
if json_ld_script:
try:
json_ld_data = json.loads(json_ld_script.string)
except json.JSONDecodeError:
pass
# Extract HTML description
description_div = soup.select_one('div.company-profile')
description = description_div.get_text(separator='\n', strip=True) if description_div else ""
# Extract posted date from title attribute
posted_date = None
date_el = soup.select_one('p.font-size-4.text-gray[title]')
if date_el:
posted_date = date_el.get('title')
job_details = {
'title': json_ld_data.get('title') if json_ld_data else None,
'description': description,
'date_posted': json_ld_data.get('datePosted') or posted_date if json_ld_data else posted_date,
'employment_type': json_ld_data.get('employmentType') if json_ld_data else None,
'valid_through': json_ld_data.get('validThrough') if json_ld_data else None,
'company': json_ld_data.get('hiringOrganization', {}).get('name') if json_ld_data else None,
'apply_url': f"{job_url}/apply",
}
return job_details
details = fetch_job_details(jobs[0]['url'])
print(details)import requests
from bs4 import BeautifulSoup
import time
def scrape_all_jobs(company_slug: str, delay: float = 1.0):
"""Scrape all jobs from a company, handling pagination."""
all_jobs = []
page = 1
while True:
html = fetch_listings_page(company_slug, page)
jobs = parse_job_listings(html, company_slug)
if not jobs:
break
all_jobs.extend(jobs)
# Check for next page
soup = BeautifulSoup(html, 'html.parser')
next_link = soup.select_one(f'a[href*="page={page + 1}"]')
if not next_link:
break
page += 1
time.sleep(delay) # Rate limiting
return all_jobs
def fetch_listings_page(company_slug: str, page: int = 1):
base_url = "https://careerspage.io"
url = f"{base_url}/{company_slug}"
if page > 1:
url = f"{url}?page={page}"
response = requests.get(url, timeout=30)
response.raise_for_status()
return response.text
all_jobs = scrape_all_jobs("recooty-inc")
print(f"Total jobs found: {len(all_jobs)}")Recooty has no public JSON API. All data must be extracted via HTML scraping using BeautifulSoup or similar parsers. Use JSON-LD structured data when available for more reliable metadata extraction.
Build parsers with multiple fallback selectors and monitor for failures. The JSON-LD structured data on detail pages is more stable than HTML selectors.
Use the sitemap at jobs.recooty.com/sitemap.xml to discover all company slugs. Parse URLs to extract unique company identifiers from the path structure.
Strip query parameters when extracting job IDs or comparing URLs. Some sitemap URLs include tracking parameters like ?src=28 that should be removed.
Implement delays between requests (1-2 seconds), use proper User-Agent headers, and handle 403/429 errors gracefully with exponential backoff.
Handle companies with no active jobs gracefully. Check for empty results before processing and log these cases for monitoring.
- 1Use sitemap parsing for efficient company discovery
- 2Parse JSON-LD structured data for reliable metadata on detail pages
- 3Implement 1-2 second delays between requests to avoid rate limiting
- 4Handle both jobs.recooty.com and careerspage.io domains
- 5Strip query parameters from URLs before extracting job IDs
- 6Use icon-based selectors (fa-location-dot, fa-briefcase) for sidebar metadata
One endpoint. All Recooty jobs. No scraping, no sessions, no maintenance.
Get API accesscurl "https://enterprise.jobo.world/api/jobs?sources=recooty" \
-H "X-Api-Key: YOUR_KEY" Access Recooty
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.