SimplyHired APIsimplyhired.com ↗
Search SimplyHired job listings by keyword and location. Returns job title, company, salary, description snippet, and direct job URL for up to 20 results per page.
What is the SimplyHired API?
The SimplyHired API provides a single search_jobs endpoint that returns up to 20 job cards per page from SimplyHired.com, covering 9 structured fields per listing including job title, company name, location, salary text, description snippet, and a direct job URL. Pagination is handled via an opaque cursor, letting you page through the full result set for any keyword and optional location query.
curl -X GET 'https://api.parse.bot/scraper/52fdd924-d5ac-4e7b-bcb0-364c29f0b718/search_jobs?query=human+resources+specialist' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace simplyhired-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: SimplyHired job search — bounded, re-runnable."""
from parse_apis.simplyhired_com_api import SimplyHired, ParseError
client = SimplyHired()
# Search for remote data-engineering jobs, cap at 5 results.
for job in client.jobs.search(query="data engineer", location="Remote", limit=5):
print(job.job_title, "|", job.company_name, "|", job.location)
if job.salary:
print(" Salary:", job.salary)
# Drill into the first result of a different query.
try:
top_hit = client.jobs.search(query="nurse practitioner", limit=1).first()
except ParseError as e:
print("Search failed:", e.code)
top_hit = None
if top_hit is not None:
print(top_hit.job_title, "at", top_hit.company_name)
print("Apply:", top_hit.job_url)
print("exercised: jobs.search")
Returns one page (up to 20 cards) of SimplyHired job search results for a keyword query, optionally narrowed to a location. Each row is one job card with title, company, location, salary text (empty string when the card shows no salary), the short description snippet, the full job page URL, and the site's job key. Results are the site's default relevance order. One request per call. Pagination is cursor-based: pass next_cursor from a previous response unchanged as cursor to fetch the following page; omit it for page 1. has_more is false and next_cursor null on the last page. total_results is the site's reported total for the query, not the number reachable in one call. A query with no matches returns an empty jobs array with count 0.
| Param | Type | Description |
|---|---|---|
| queryrequired | string | Job title, skills, or company keywords to search for. |
| cursor | string | Opaque continuation token: next_cursor from a previous search_jobs response for the same query and location. Omitted = first page. |
| location | string | City, state, ZIP, or "Remote" to narrow results (e.g. Austin, TX). Omitted = nationwide. |
{
"type": "object",
"fields": {
"jobs": "array of job cards: job_title, company_name, location, salary (string, empty when not shown), description_snippet, job_url (absolute), job_key (site identifier)",
"count": "integer number of jobs in this page",
"has_more": "boolean, true when next_cursor is present",
"next_cursor": "string cursor for the next page, or null on the last page",
"page_number": "integer 1-based page number of this response",
"total_results": "integer total matching jobs reported by the site"
},
"sample": {
"data": {
"jobs": [
{
"salary": "$75,000 - $85,000 a year",
"job_key": "8x70Dw9N0YBy6emGlpuM3jB5CtPgLotwlaFY4EPxCPf8yFMS_yJ9Jg",
"job_url": "https://www.simplyhired.com/job/8x70Dw9N0YBy6emGlpuM3jB5CtPgLotwlaFY4EPxCPf8yFMS_yJ9Jg",
"location": "Remote",
"job_title": "Human Resources Generalist",
"company_name": "Petfolk",
"description_snippet": "Compliance Knowledge: Working knowledge of federal, state, and local employment laws; multi-state workforce experience is a plus."
},
{
"salary": "",
"job_key": "aYip2yYGHmeEXTLKYlrP7OoDqJweTIDKqBFywzDIekYnc12_32Q3rg",
"job_url": "https://www.simplyhired.com/job/aYip2yYGHmeEXTLKYlrP7OoDqJweTIDKqBFywzDIekYnc12_32Q3rg",
"location": "Hunter, VA",
"job_title": "Human Resource Coordinator",
"company_name": "Digimixes LLC",
"description_snippet": "Bachelor's degree in human resources, Business Administration, or a related field."
}
],
"count": 20,
"has_more": true,
"next_cursor": "ABQAAQAUAAAAAAAAAAAAAAACZKpNewEBAQtLVPpKpRcu0+7uPIDlrdDU4TyXivp7Xv3W8Wg+FtIUJ7usBnQI0ID3kFDQs6/ZsEQL",
"page_number": 1,
"total_results": 17337
},
"status": "success"
}
}About the SimplyHired API
What the API returns
The search_jobs endpoint accepts a required query parameter (job title, skills, or company keywords) and an optional location string such as a city, state, ZIP code, or the literal string "Remote". Omitting location returns nationwide results. Each response includes a jobs array where every element contains job_title, company_name, location, salary (a plain string, empty when the listing does not display one), description_snippet, and job_url as an absolute link to the listing on SimplyHired.
Pagination
Every response includes page_number (1-based integer), count (listings on this page, up to 20), total_results (total matching jobs reported by SimplyHired), and has_more (boolean). When has_more is true, a next_cursor string is present. Pass that cursor as the cursor parameter on your next call — keeping query and location identical — to fetch the following page. On the last page, next_cursor is null and has_more is false.
Salary data
Salary is returned as a free-form string exactly as it appears on the job card (e.g. "$55,000 - $70,000 a year" or "$28 an hour"). When a listing does not display compensation, the field is an empty string rather than null, so no null-check is required. Parsing the salary range into numeric values requires your own post-processing.
Source coverage
SimplyHired aggregates listings from employer career pages, staffing agencies, and other job boards, so the total_results figure can be large for broad queries. Results reflect SimplyHired's own ranking and deduplication logic. There is no built-in filter for job type (full-time, part-time, contract) or date posted beyond what the query string and location provide.
The SimplyHired API is a managed, monitored endpoint for simplyhired.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when simplyhired.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official simplyhired.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a job alert tool that polls search_jobs for new listings matching a skill keyword in a specific city.
- Aggregate salary strings across hundreds of listings to analyze compensation ranges for a given role.
- Power a job board widget that surfaces SimplyHired results filtered to a ZIP code for a local workforce site.
- Feed a recruiter dashboard with real-time company_name and job_title counts to track competitor hiring activity.
- Compare job_url density by location field to identify which metro areas have the most open positions for a title.
- Collect description_snippet text in bulk to train or fine-tune a job-matching NLP model.
- Monitor total_results over time for a query to detect hiring trend changes in a specific industry.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does SimplyHired have an official developer API?+
What does the salary field contain, and what happens when a listing has no salary?+
salary field is a plain string copied from the job card (for example, "$60,000 - $75,000 a year" or "$22 an hour"). When the listing shows no salary information, the field is an empty string. The API never omits the field, so you can always check its length without a null guard.Can I filter results by job type (full-time, part-time, contract) or date posted?+
search_jobs endpoint does not expose job-type or date-posted filter parameters — only query, location, and cursor are accepted. You can fork this API on Parse and revise it to add those filter inputs if SimplyHired surfaces them in its results.Does the API return the full job description or only a snippet?+
description_snippet — the short excerpt shown on the search results page — and a job_url pointing to the full listing. Full job description text (the complete posting) is not returned by this endpoint. You can fork the API on Parse and add a job-detail endpoint that fetches the full description from each job_url.How does cursor-based pagination work, and can I jump to an arbitrary page?+
next_cursor token returned in each response. You must pass the previous response's next_cursor value to retrieve the next page; you cannot skip to an arbitrary page number. The page_number field in each response tells you where you are in the sequence, but random access is not supported by this endpoint.