Skip to main content
Glama
Ethos6

jobsearch

by Ethos6

Free Job Search API

Your own job search API. Free forever, no API keys, no quotas.

Write a few lines about the job you want, or upload your CV, and get the best matching jobs from company career pages, public job boards and the web: ranked, explained and linked to the original posting.

CI Live check License: MIT Python 3.10+ MCP

Quick start · API · CV upload · Alerts · MCP · Sources · Config

Screenshot with sample data from the offline demo (scripts/demo_server.py).

Example

curl -s localhost:8000/v1/search -H 'content-type: application/json' -d '{
  "requirements": "Backend developer, 6 years with Python and Django. Remote in Europe or hybrid in Berlin. At least €80k. Full-time. No crypto or gambling companies."
}'
{
  "requirements": {                      // how your words were understood
    "titles": ["backend engineer"], "skills": ["python", "django"], "work_modes": ["remote", "hybrid"],
    "places": [{"name": "Europe", "kind": "continent"}, {"name": "Berlin", "country": "DE", "kind": "city"}],
    "seniority": "senior", "years_experience": 6, "salary_min": 80000, "salary_currency": "EUR",
    "employment_types": ["full_time"], "exclude": ["crypto", "gambling"]
  },
  "results": [{
    "score": 96,
    "job": { "title": "Senior Backend Engineer (Python)", "company": "…", "location": "Remote, Europe",
             "url": "https://job-boards.greenhouse.io/…", "source_name": "Greenhouse",
             "salary": {"min": 90000, "max": 120000, "currency": "EUR"}, "posted_at": "2026-10-15T…" },
    "reasons": ["Role matches “backend engineer”", "Uses Python, Django", "Remote", "Senior level", "Pays €90k–120k/year"],
    "warnings": []
  }],
  "total_found": 37,
  "sources": [{"id": "index", "jobs": 412}, {"id": "web", "jobs": 18}, {"id": "linkedin", "skipped": "off by default …"}]
}

Related MCP server: Google Jobs Scraper MCP

What it understands

Write the way you'd tell a friend. The built-in parser needs no AI and no keys:

You write

It understands

"backend developer", "SRE", "Go engineer", "beekeeper"

68 role families with 400+ ways to say them, or the words you used

"Python, Django, k8s, Figma, patient care"

285 skills, 400+ names with aliases

"ideally Kubernetes", "AWS is a plus"

nice-to-have skills

"Berlin", "Bangalore", "remote in Europe", "UK", "LATAM"

cities, countries, regions (2,000 cities, all countries)

"I live in Pune", "based in Lisbon"

where you live, so remote jobs limited to other countries are skipped

"remote", "hybrid", "fully remote", "not fully remote"

work mode

"junior", "6 years of experience", "senior"

level

"$120k", "€80,000 a year", "35 LPA", "£45/hour", "12000 AED per month", "$80-100k"

minimum salary, currency and period

"full-time", "contract", "part-time is fine", "internship"

job type

"need visa sponsorship", "I have a Blue Card"

visa needs

"posted in the last 2 weeks"

freshness

"no crypto or gambling", "not interested in agencies", "avoid Amazon"

things to avoid

"I speak German and English"

languages (warns when a job asks for one you didn't list)

Optional AI: point JOBS_LLM_URL at any OpenAI-compatible API (a free local Ollama works) for even better understanding of long requests and CVs, and AI re-ranking of the top matches.

Search with your CV

Upload a CV (PDF, Word .docx or text). The API reads your recent job titles, skills, years of experience (from the dates on your CV), seniority, location and languages. Add a location or a few lines and they take priority over the CV.

curl -s localhost:8000/v1/search/cv -F cv=@my_cv.pdf                                  # CV only
curl -s localhost:8000/v1/search/cv -F cv=@my_cv.pdf -F location="remote" \
     -F requirements="no agencies, at least \$100k"                                     # CV + your wishes

Privacy: the CV is read in memory, in a separate process with strict limits, and never stored, logged or sent to job sites. Only short search words (like "data engineer python Bengaluru") leave the server, and the CV text is not echoed back. If you turn on an outside AI service, the CV goes to that service.

Quick start

Docker Compose (recommended, includes your own web search engine)

git clone https://github.com/Ethos6/free-job-search-api && cd free-job-search-api
cp .env.example .env
docker compose up -d        # web page and API on http://localhost:8000, docs at /docs

The first start fills a local job index from the company boards and job boards in the background; searches get richer over the first few minutes.

pip

pip install "free-job-search-api[mcp] @ git+https://github.com/Ethos6/free-job-search-api"
jobsearch serve                                   # http://localhost:8000
jobsearch search "nurse in Berlin, speak German" --refresh
jobsearch search --cv my_cv.pdf --location remote

Try it offline (sample data, no internet needed): python scripts/demo_server.py 8010

API

Interactive docs are at /docs.

Endpoint

What it does

POST /v1/search

{"requirements": "...", "location": "...", "limit": 25} → ranked jobs with reasons

GET /v1/search?q=...

the same, as a GET

POST /v1/search/cv

multipart: cv file, optional requirements, location, limit

POST /v1/understand

see how a request is understood, without searching

GET /v1/sources

every source, whether it's on, and what it asks of us

POST /v1/alerts

save a search (see below)

Every job comes with a score out of 100, plain-language reasons and warnings (e.g. "Salary not listed", "Remote only for people in: US"), the original url, the source_name to credit, and also_on links when the same job appears on several sources.

Alerts

Save any search and get new matches as they appear: by webhook (Slack, Discord, Zapier, your app) and a private RSS feed. No email address needed.

curl -s localhost:8000/v1/alerts -H 'content-type: application/json' \
  -d '{"requirements": "senior react developer, remote", "every_hours": 24, "webhook_url": "https://hooks.example.com/abc"}'
# -> {"id": "...", "token": "...", "feed_url": ".../v1/alerts/<id>/feed.xml?token=..."}

On the web page, press Get alerts for new matches after a search (this works for CV searches too, without sending the CV again).

MCP server for AI agents

Let Claude, Cursor or any MCP client search jobs for you:

{ "mcpServers": { "jobsearch": { "command": "jobsearch", "args": ["mcp"] } } }

Tools: search_jobs(requirements, location, limit), search_jobs_from_cv(cv_text, requirements, location, limit), job_sources().

Where jobs come from

Source

How

Notes

Company career boards: Greenhouse, Lever, Ashby, Workable, Recruitee

official public job-board APIs, indexed locally

Starts with about 150 verified companies (Stripe, OpenAI, Airbnb, Databricks, Notion, SpaceX, Spotify…) and grows by itself: every board found through web search or in job posts is added. Add your own with JOBS_COMPANIES.

SmartRecruiters

public API, searched live

large employers (Bosch, Accor, Sodexo, Ubisoft…)

Remotive, Remote OK, Jobicy, Arbeitnow

free public job-board APIs, indexed

each credited and linked, as they ask

The Muse, Himalayas

public APIs, searched live

Hacker News "Who is hiring?"

public HN Algolia API

the monthly thread, parsed into jobs

The web

your own FreeSearch API

finds postings anywhere; reads the schema.org JobPosting data sites publish for search engines

LinkedIn, Indeed, Glassdoor…

public pages, off by default

see below

About LinkedIn, Indeed, Glassdoor and similar sites. Their terms forbid automated access. By default the API never fetches their pages; when web search finds one of their postings, it shows the title and the link so you can open it yourself. If you run the API and accept that responsibility, JOBS_ENABLE_BIG_SITES=1 turns on LinkedIn's public (logged-out) job search and reading their job pages. Even then: no login, no CAPTCHA solving, no disguised browsers, no proxy rotation. If a site refuses, the API backs off and skips it. Most jobs on those sites are also on the employer's own career board, which the API reads directly.

Being a good citizen. The API identifies itself honestly, paces requests per site, caches results, refreshes its index every few hours instead of on every search, and always links to the original posting and names the source.

How ranking works

Each job is scored out of 100: role and title 35, skills 25, location and work mode 15, seniority 10, salary 10, freshness 5. Hard filters remove jobs you ruled out: things to avoid, a work mode or place you can't do, pay clearly below your minimum (other currencies are converted approximately and labelled so), postings older than you asked for, and remote jobs open only to people in other countries. Duplicates across sources are merged, keeping the company's own posting.

Configuration

All optional. See .env.example.

Variable

Default

Meaning

JOBS_SEARCH_URL

–

FreeSearch API base URL for web search (set by docker-compose)

JOBS_LLM_URL, JOBS_LLM_MODEL, JOBS_LLM_KEY

–

optional OpenAI-compatible AI (e.g. Ollama)

JOBS_API_KEYS

–

require X-API-Key (comma-separated keys)

JOBS_RATE_LIMIT

20

searches per minute per client

JOBS_COMPANIES

–

extra boards, e.g. greenhouse:acme,lever:example

JOBS_SOURCES

all

only use these source ids

JOBS_REFRESH_HOURS

6

how often the local index is refreshed

JOBS_ENABLE_BIG_SITES

0

LinkedIn / Indeed / Glassdoor pages (see above)

JOBS_TIMEOUT

20

seconds a search may take

JOBS_DATA

./data

where the index database lives

JOBS_BASE_URL

http://localhost:8000

public address, used in alert links

JOBS_TRUST_PROXY

0

set 1 behind a reverse proxy

Development

pip install -e ".[dev]"
pytest -q                      # 96 tests, no internet needed
python scripts/live_check.py   # searches the real sources (needs internet)

The Live check workflow runs real searches against the real sources every week.

License and credits

MIT. City and continent data from GeoNames (CC BY 4.0); country names from ISO 3166. Job listings belong to the employers and job boards they come from; this project only links to them. Not affiliated with any job board or employer.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to pull live job listings from major ATS platforms (Greenhouse, Lever, Ashby, Workable), Hacker News hiring threads, and detect hiring signals on company career pages.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to search Google Jobs and retrieve structured job listings, including titles, companies, locations, descriptions, and direct apply links, through natural language queries. Supports location targeting, country/language filters, and pagination.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to search remote job listings, read full descriptions and structured metadata, compare roles, and retrieve original application links when the account's subscription and scopes allow.
    26 npm
    MIT
  • F
    license
    B
    quality
    B
    maintenance
    Enables AI assistants to search and filter job listings across multiple platforms like Indeed, LinkedIn, and Glassdoor, returning structured results for easy processing.
    1
    -