Parse a job description
A job posting hides its most useful information inside paragraphs of boilerplate about culture and benefits. This endpoint reads a job description the way a sourcing recruiter does and pulls out the parts that actually drive matching — required skills, years of experience, seniority, location, salary range — as clean structured data.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The gap between a posting and a searchable requirement
Job boards, applicant tracking systems and internal wikis all publish postings in free text, which is great for a human skimming a page and useless for software trying to match candidates against open roles at scale. This endpoint closes that gap: it takes the raw description, whether copied from a careers page or exported from an ATS, and returns the requirement in a form your matching logic can actually query.
How a request moves through the system
Post the job description to POST /ocr/job-post and you get a task_id back right away, since the extraction runs asynchronously in the background. The structured result — skills, requirements, seniority, compensation fields when present — arrives through a signed webhook, or you can pull it from a signed link that remains valid for 24 hours after the task completes.
Postings evolved, but the ambiguity never left
Job postings moved from newspaper classifieds to job boards decades ago, yet the core problem never went away: two companies describing the same role use entirely different words for the same requirement — 'proficient in spreadsheets' versus 'advanced Excel' versus 'strong quantitative skills.' Extracting structure means recognizing that overlap, not just copying phrases verbatim, which is where this endpoint earns its keep over a plain keyword search.
Where this fits in a hiring stack
Aggregators use it to normalize postings scraped from dozens of sources into one taxonomy; internal HR tools use it to auto-tag open requisitions with skill codes; matching engines use the output as the counterpart to a parsed resume, so both sides of the comparison speak the same structured language.
Straightforward, published pricing
Each extraction costs $0.003 per request plus $0.0135 per document, charged only on a successful parse; failures are retried up to three times automatically and never billed if they still don't succeed. Since access requires prepaid balance rather than a free tier, the endpoint stays fast and predictable without throwaway traffic slowing it down.
What you can do with it
Job board aggregation
Normalize thousands of postings scraped from different career sites into one consistent schema for search and filtering.
Candidate-to-job matching
Pair extracted job requirements with parsed resume data to score fit automatically instead of relying on manual keyword search.
Salary and market analysis
Pull compensation ranges and seniority levels out of thousands of postings to track hiring trends across a market or industry.
Internal ATS auto-tagging
Automatically tag open requisitions with structured skill and seniority fields as soon as a hiring manager submits the posting.
FAQ
What data does the job description parser api extract?
Required skills, seniority level, years of experience, location, and compensation details when the posting includes them.
Can it handle postings from any job board format?
Yes, it reads free-text descriptions regardless of the source site's layout or how the posting was copied or exported.
Is there a free trial for the job description parser api?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How do I receive the extracted results?
Via a signed webhook when processing completes, or from a signed link that stays valid for 24 hours.
Does a failed extraction cost anything?
No. Failed tasks retry automatically up to three times and are never charged; billing only applies to successful parses.
Can I process job postings in bulk?
Yes, submit each posting as its own request; every call is asynchronous with its own task_id so batches run concurrently.
What is the price of the job description parser api?
$0.003 per request plus $0.0135 per document, published openly with no hidden credits.
Does the parser recognize synonymous skill phrasing?
It is built to read requirements the way a recruiter would, capturing intent rather than only matching exact keyword strings.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/ocr/job-post \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/ocr/job-post", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/ocr/job-post",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/ocr/job-post", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/ocr/job-post", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "ocr.job_post",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 10 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |