Comeet Jobs API: Get Comeet Job Listings as JSON
TL;DR
Comeet (now Spark Hire Recruit) career pages at comeet.com/jobs/{slug}/{companyId} embed every open position as a JSON array assigned to COMPANY_POSITIONS_DATA in the page HTML, so one request with no API key returns all jobs with full descriptions. Both the slug and the company ID are required. Descriptions are split into named sections, the only date is time_updated, the country is an ISO code, and the state field isn't reliable.
On this page
To get a company's jobs from Comeet, fetch its career page at https://www.comeet.com/jobs/{slug}/{companyId} and parse the COMPANY_POSITIONS_DATA JSON array embedded in the HTML. That one request returns every open position with its full description, and no API key is needed.
That's the DIY route, and it works for a handful of companies you already know. If you'd rather not build and maintain a Comeet scraper, CleanJobData already ingests ATS platforms and company career sites and serves the jobs normalized through one REST API — see the Jobs API docs.
At a Glance
| Endpoint | GET https://www.comeet.com/jobs/{slug}/{companyId} (JSON embedded in HTML) |
| API key | None |
| Pagination | None: the page holds every open position |
| Full description | Yes, in custom_fields.details |
| Salary field | No |
| Remote | workplace_type (Remote, Hybrid, On-site) |
Comeet has been rebranded as Spark Hire Recruit, but career pages still live on comeet.com.
Finding the Slug and Company ID
A Comeet career page URL has two parts after /jobs/: a slug and a company ID, as in https://www.comeet.com/jobs/acme/12.345. Job pages add a title slug and a position ID: https://www.comeet.com/jobs/acme/12.345/senior-engineer/AB.123. Both the slug and the company ID are required, and you can't derive one from the other:
comeet.com/jobs/acmewithout the company ID returns a 404.- A real slug with the wrong company ID returns HTTP 200, but with a small generic page instead of the company's data.
Copy both values from a real job or careers link. If the company embeds its Comeet jobs on its own site, look for comeet.com/jobs/ links in the page or the Network tab.
The Request
curl "https://www.comeet.com/jobs/acme/12.345"The response is an HTML page. Its inline script declares a few variables and then assigns them, and one of them holds every open position:
<script type="text/javascript">
var COMPANY_DATA;
var COMPANY_POSITIONS_DATA;
var POSITION_DATA;
COMPANY_DATA = {"name": "Acme", ...};
COMPANY_POSITIONS_DATA = [ {...}, {...} ];
POSITION_DATA = null;
</script>Note that the variables are declared first and assigned later without var. A pattern that looks for var COMPANY_POSITIONS_DATA = finds nothing on most pages; match the bare assignment instead.
One position looks like this (trimmed):
{
"uid": "7D.766",
"name": "Senior Backend Engineer",
"employment_type": "Full-time",
"experience_level": "Senior",
"workplace_type": "Hybrid",
"time_updated": "2026-09-23T13:18:21Z",
"location": {
"name": "Austin, TX",
"city": "Austin",
"state": "TX",
"country": "US",
"is_remote": false
},
"custom_fields": {
"details": [
{ "name": "Description", "value": "<p>We're looking for...</p>", "order": 0 },
{ "name": "Requirements", "value": "<ul><li>5+ years...</li></ul>", "order": 1 }
]
},
"url_comeet_hosted_page": "https://www.comeet.com/jobs/acme/12.345/senior-backend-engineer/7D.766",
"url_active_page": "https://www.comeet.com/jobs/acme/12.345/senior-backend-engineer/7D.766"
}Position Fields
| Field | What it holds |
|---|---|
uid | Position ID; multi-location jobs use {base}-{suffix} (see below) |
name | Job title |
employment_type | Full-time, Part-time, Hourly or None |
experience_level | Entry-level, Intermediate, Senior, Management or None |
workplace_type | Remote, Hybrid or On-site |
time_updated | ISO timestamp of the last update |
location | name, city, state, country (ISO alpha-2) and is_remote |
custom_fields.details | Ordered description sections, each with name, value (HTML) and order |
url_comeet_hosted_page | The job page on comeet.com |
url_active_page | A second public URL for the job; use it when the hosted-page URL is missing |
None in employment_type or experience_level means "not set", not a real value. It's common.
Fetching Jobs (Python)
import json
import re
import requests
POSITIONS_RE = re.compile(r"\bCOMPANY_POSITIONS_DATA\s*=\s*")
def fetch_comeet_jobs(slug: str, company_id: str) -> list:
r = requests.get(f"https://www.comeet.com/jobs/{slug}/{company_id}", timeout=30)
r.raise_for_status()
html = r.text
if not re.search(r"\bCOMPANY_DATA\s*=", html):
raise ValueError("No company data: check the slug and company ID")
match = POSITIONS_RE.search(html) # skips the bare "var ...;" declaration
if not match:
raise ValueError("COMPANY_POSITIONS_DATA not found: the page layout may have changed")
positions, _ = json.JSONDecoder().raw_decode(html, match.end())
# Group multi-location rows ("BASE-SUFFIX") into one job per base uid
groups = {}
for p in positions:
groups.setdefault(p["uid"].split("-")[0], []).append(p)
jobs = []
for base, rows in groups.items():
primary = next((p for p in rows if p["uid"] == base), rows[0])
sections = sorted(primary.get("custom_fields", {}).get("details") or [], key=lambda d: d.get("order", 0))
html_desc = "".join(
(f"<h3>{s['name']}</h3>" if s.get("name") else "") + s["value"]
for s in sections if (s.get("value") or "").strip()
)
locations = []
for p in rows:
loc = p.get("location") or {}
place = loc.get("city") or loc.get("name")
if place and place.lower() != "remote":
locations.append({"place": place, "country": loc.get("country") or None})
jobs.append({
"id": base,
"title": primary.get("name"),
"updated": primary.get("time_updated"),
"workplace_type": primary.get("workplace_type"),
"employment_type": primary.get("employment_type"),
"experience_level": primary.get("experience_level"),
"locations": locations,
"url": primary.get("url_comeet_hosted_page") or primary.get("url_active_page"),
"html": html_desc,
})
return jobsraw_decode reads exactly one JSON value starting at the assignment and ignores the rest of the script, which is safer than a regex that tries to find the closing bracket.
Gotchas
Multi-location jobs appear as several positions. A job posted to several locations shows up as rows that share a base ID with different suffixes, for example 7D.766, 7D.766-80.50D and 7D.766-4B.10E. The rows match except for location, and the base row often has no city. Group by the part before the first hyphen and merge the locations, or you'll store one job several times. Deduplicating job listings covers the general problem.
Don't trust location.state. We've seen postings for Austin, Texas carry state: "AZ". Use city and country, and resolve the state yourself if you need it. country is a clean ISO alpha-2 code.
Structured location can be empty. Some on-site jobs have city, state and country all blank while location.name still holds the place, such as "Memphis, TN". Fall back to name and parse it. See the location normalization guide.
The only date is time_updated. There's no original posting date. time_updated changes when the employer edits the job, so "updated recently" doesn't always mean "posted recently."
A wrong ID doesn't return an error. A nonexistent company, or a real slug with the wrong company ID, returns HTTP 200 with a generic marketing page. Check that the page contains a COMPANY_DATA assignment before you trust an empty result.
Description sections vary by company. Section names and counts are set per employer, commonly two to four sections such as "Description", "Requirements" and a benefits section. Join every section in order rather than looking for fixed names. The values are real HTML, not entity-encoded.
Experience level needs mapping. Intermediate and Management don't line up with every seniority scale. The experience level mapping guide shows one way to map them.
There's no salary field. If pay is disclosed, it's in the description text.
Embedded Data vs Comeet's Official API
Comeet also has a documented careers API for its customers. It needs credentials that the employer generates in its own Comeet account, so you can only use it for companies that give you access. For published jobs from other companies, the data embedded in the public career page is the route that works.
When This Is Enough
For one company, a single page fetch gets every open job with full descriptions. It's one of the cheapest platforms to collect from.
When It Isn't
Across many companies and platforms you end up maintaining a different collector for each, with different identifiers, date fields and location quirks. The ATS public job postings API list shows how they compare.
CleanJobData reads Comeet career pages alongside other platforms and returns one schema, with locations resolved to cities, states and countries, a remote type, an employment type and an experience level. Comeet has no salary field, so salary is only filled when the description states it. Try it in the Playground or see the API Documentation.
Skip the scraper: get this data from the CleanJobData API
If you'd rather not maintain a Comeet collector, you can query normalized jobs from ATS platforms and company career sites with a single request. The response has structured city/state/country locations, parsed salary when the employer publishes one, a remote type, and company metadata, and you page through results with the cursor in pagination.next_page.
curl "https://api.cleanjobdata.com/jobs?title=engineer&domain=www.comeet.com&limit=20" \
-H "Authorization: Bearer $CLEANJOBDATA_API_KEY"The domain filter is an exact match on the host of each job's application_url, so it only returns jobs whose apply link resolves to www.comeet.com; use company_website_url or employer_id to scope to one employer instead. Coverage depends on which employers are in the dataset, so check that the companies you care about appear before you rely on it.
- Jobs API reference for every filter and response field
- Playground to run queries without writing code
- Pricing — the Trial is free with no card required
FAQ
Does Comeet have a public jobs API?
Not a public JSON endpoint, but every Comeet career page at comeet.com/jobs/{slug}/{companyId} embeds all open positions as a JSON array named COMPANY_POSITIONS_DATA. One request with no API key returns every job with its full description.
How do I find a company's Comeet company ID?
It's the second path segment after /jobs/ in any of the company's Comeet URLs, such as 12.345 in comeet.com/jobs/acme/12.345. You need both the slug and the company ID; neither works alone.
Why does my Comeet request return no jobs?
Check the company ID. A wrong ID returns HTTP 200 with a generic page that has no COMPANY_DATA or positions, so it looks like an empty board rather than an error.
Does Comeet include a posting date or salary?
There's no salary field, and the only date is time_updated, the last time the position was edited. Pay, when it's disclosed, appears in the description text.