Skip to main content
Glama
psflwork

naukri-job-hunter

by psflwork
README.md
# Naukri Job Hunter

Find **remote jobs** and **side gigs** (part-time, freelance, contract) on
[naukri.com](https://www.naukri.com), score every job against **your resume**, get a ranked HTML
report, and optionally auto-apply. Works as a one-command script or as an **AI agent** (MCP server for
Cursor, Claude Desktop and other MCP clients).

- One command: `./run.sh`; a first-run wizard sets everything up
- Resume-based match score (0-100) with matched skills per job
- Two hunts: regular remote jobs, and side gigs you can do alongside a job
- Only shows new jobs each run; HTML + CSV reports
- Choose how to apply: auto-apply, pick jobs from a numbered list, or get a **contact list**
  (recruiter emails, phones, company links, prefilled email drafts) to send your resume yourself
- Auto-apply has a dry run, confirmation and daily caps
- Your resume, login and results stay on your machine

## Quick start

```bash
git clone https://github.com/psflwork/naukri-job-hunter.git
cd naukri-job-hunter
./run.sh
```

The first run:

1. creates a Python environment and installs dependencies,
2. asks for your **resume PDF** (drag the file into the terminal), **years of experience** and the
   **roles** you want,
3. asks for your **Naukri email/password** (optional; saved only locally in `.env`), then
4. opens Chrome, searches Naukri, scores the jobs and opens the report, then shows a menu:

```text
What next?
  [a] Auto-apply to 4 eligible jobs (of top 10)
  [p] Pick jobs to apply to
  [c] Contact list: emails / phones / links to send your resume manually
  [o] Open top 10 jobs in your browser
  [q] Quit
```

After that, just run `./run.sh` (regular jobs) or `./run.sh side` (side gigs) whenever you want.

**Requirements:** Python 3.10+ and [Google Chrome](https://www.google.com/chrome/). macOS and Linux
work out of the box; on Windows use [WSL](https://learn.microsoft.com/windows/wsl/install) or Git Bash.

> Run it as `./run.sh` from the project folder (with the `./`). It uses its own Python in `.venv`,
> so you never need to activate anything.

## Usage

```bash
./run.sh                 # regular hunt: search, report, then the menu above
./run.sh side            # side-gig hunt (part-time / freelance / contract)
./run.sh --no-apply      # search + report only
./run.sh --apply         # auto-apply without the menu (for scheduled runs)
./run.sh --all           # include jobs already seen in earlier runs
./run.sh --limit 10      # only the 10 best matches this run (default: max_results in config)
./run.sh --top 20        # consider the top 20 matches in the menu
./run.sh setup           # re-run the setup wizard
```

### Shortcuts

Work on the latest search results; put `side` first for the gig hunt (`./run.sh side pick`).

| Shortcut | What it does |
|---|---|
| `./run.sh pick` | Numbered list of matches; type `1,3,5-7` to apply to those (or `a` for all auto-applicable). Company-site / questionnaire jobs open in your browser |
| `./run.sh contacts` | Contact list for sending your resume yourself: recruiter emails and phones published in the job posts, company website/address, **Draft email** button (prefilled subject + message), and LinkedIn-recruiter / careers-page links |
| `./run.sh open --top 10` | Open the top 10 matches in your browser |
| `./run.sh apply --top 10` | Dry run: what would be auto-applied (`--confirm` to apply) |
| `./run.sh search` | Search + report only |
| `./run.sh login` | Log in and save the session |

The contact list only shows emails/phones that recruiters actually published (Naukri hides recruiter
details otherwise); it never guesses addresses. Edit the email template under `outreach` in your
config.

Search every morning at 9:00 without applying (`crontab -e`):

```bash
0 9 * * * cd /path/to/naukri-job-hunter && ./run.sh --no-apply --no-open >> output/cron.log 2>&1
```

## How it works

```mermaid
flowchart LR
    You([You]) -->|"chat: find remote jobs"| Agent[AI agent<br/>Cursor / Claude]
    You -->|./run.sh| CLI[run.sh → hunt.py]
    Agent -->|MCP tools| MCP[mcp_server.py]
    MCP --> Core
    CLI --> Core

    subgraph Core[Core]
        Search[run_search] --> Matcher[matcher.py<br/>score 0-100]
        Naukri[naukri.py<br/>Playwright + Chrome]
    end

    Search --> Naukri
    Naukri -->|visible Chrome window| Site[(naukri.com<br/>jobapi/v3/search<br/>jobapi/v4/job)]
    Resume[/your resume PDF/] --> Matcher
    Config[/config.yaml/] --> Search
    Env[/.env credentials/] --> Naukri

    Matcher --> Out[output/*.html + *.csv]
    Matcher --> State[(data/<br/>seen, applied,<br/>latest results,<br/>browser session)]
```

1. **Search**: for each query in the config, a real Chrome window opens Naukri's search page with
   the Remote, experience and posted-in-last-N-days filters. The script reads the JSON the page
   itself loads, so it doesn't depend on the page's HTML layout.
2. **Filter**: drops excluded titles/companies, jobs already applied to, and jobs seen in earlier
   runs.
3. **Score**: each job gets 0-100 against your resume:

   | Part | Points | Based on |
   |---|---|---|
   | Skills | 50 | `skills` from config found in the job, plus job tags found in your resume |
   | Title | 25 | `strong_titles` / `target_titles` in the job title |
   | Experience | 15 | your years inside the job's min-max range |
   | Remote | 10 | location says Remote |

4. **Report**: jobs at or above `min_score` go to `output/jobs_<timestamp>.html` and `.csv`.
5. **Apply (optional)**: clicks Naukri's own Apply button. Company-site jobs and jobs with recruiter
   questionnaires are left for you to apply manually.

### Two hunts: regular jobs and side gigs

| Hunt | Command | Config | Looks for |
|---|---|---|---|
| Regular | `./run.sh` | `config.yaml` | Full-time remote roles matching your queries |
| Side gigs | `./run.sh side` | `config.side.yaml` | Remote part-time, freelance, contract or second-job work for developer / full-stack / architect roles; salary ignored |

Each hunt keeps its own "already seen" history and report (`output/side_jobs_*.html`); applied jobs
are shared, so you never apply twice. Add more hunts by creating `config.<name>.yaml` and running
`./run.sh <name>`.

Naukri has no part-time filter, so the side hunt works differently:

```mermaid
flowchart LR
    Q["Gig keywords<br/>freelance, part time,<br/>contract developer..."] --> S[Naukri search<br/>remote, last 30 days]
    S --> G{Gig signal?<br/>part-time, freelance,<br/>6 months contract,<br/>secondary income...}
    G -- no --> X[dropped]
    G -- yes --> F{Tech role and<br/>not junior?}
    F -- no --> X
    F -- yes --> Sc["Score<br/>skills 45, gig 20,<br/>title 15, exp 10, remote 10"]
    Sc --> R[side_jobs report<br/>with Gig signals column]
```

- **Gig signal required**: phrases like *part-time, freelance, contractual, 6 months contract,
  secondary income, hourly* in the job. A bare *contract/weekend/consultant* only counts in the title,
  and noise such as *contract testing* or *smart contracts* is ignored.
- **Filters**: drops non-tech titles (teacher, sales, accountant, ...), jobs with none of your
  skills, and junior gigs (experience range below 5 years).

## AI agent (MCP)

`mcp_server.py` exposes the hunter as MCP tools, so an AI assistant can search, read job details,
shortlist with reasons, write a tailored pitch, and apply only to the jobs you approve.

**Cursor**: the server and an agent rule (`.cursor/rules/naukri-job-hunter.mdc`) are already set up
in this repo. Open the folder in Cursor, enable `naukri-job-hunter` under **Settings → MCP**, then
ask e.g. *"Find remote senior developer jobs from the last 3 days and shortlist the best 5"* or
*"Find part-time or freelance gigs I can do alongside my job."*

**Claude Desktop / other MCP clients**: run `./run.sh setup` once, then add:

```json
{
  "mcpServers": {
    "naukri-job-hunter": {
      "command": "/path/to/naukri-job-hunter/.venv/bin/python",
      "args": ["/path/to/naukri-job-hunter/mcp_server.py"]
    }
  }
}
```

```mermaid
sequenceDiagram
    actor You
    participant A as AI agent
    participant M as MCP server
    participant N as naukri.com

    You->>A: "Find remote engineering jobs"
    A->>M: get_candidate_profile
    M-->>A: resume text + preferences
    A->>M: search_jobs
    M->>N: search pages (logs in from .env if needed)
    N-->>M: job JSON
    M-->>A: ranked matches + report path
    loop top 5-8 jobs
        A->>M: get_job_details(job_id)
        M->>N: job page
        M-->>A: full JD, skills, applicants
    end
    A-->>You: shortlist with fit + tailored pitch
    You->>A: "Apply to #1 and #3"
    A->>M: apply_to_job(job_id, confirm=true)
    M->>N: click Apply
    M-->>A: applied / needs_manual
    A-->>You: results
```

| Tool | Purpose |
|---|---|
| `get_candidate_profile` | Resume text and preferences of a hunt profile |
| `search_jobs` | Search, score and rank (`profile="side"` for gigs); writes the report |
| `list_matches` | Filter a profile's latest results without re-searching |
| `get_job_details` | Full description, key skills, role, industry, applicants, company |
| `login_status` / `login` | Check or refresh the Naukri session |
| `apply_to_job` | Preview by default; applies only with `confirm=true` |
| `get_contacts` | Recruiter emails/phones, company links and email drafts for manual outreach |
| `list_applied` | Jobs already applied to |

## Configuration

`./run.sh setup` creates `config.yaml` and `config.side.yaml` from [`examples/`](examples/) and fills
in your resume, experience and roles. Edit them any time to tune results:

| Key | Meaning |
|---|---|
| `profile_name` | Heading shown in the report |
| `resume_path` | Your resume PDF (empty = first PDF in the folder) |
| `queries` | Search keywords, each searched separately |
| `experience_years` | Your experience; used for scoring |
| `search.experience_filter` | Naukri experience filter (defaults to `experience_years`; `null` = none) |
| `search.remote_only` / `job_age_days` / `max_pages_per_query` | Search filters and depth |
| `search.min_delay_seconds` / `max_delay_seconds` | Random pause between page loads |
| `strong_titles` / `target_titles` | Title words worth full / partial title points |
| `exclude_title_keywords` / `exclude_companies` | Jobs to drop |
| `skills` | Your core skills; drive the skill score |
| `min_skill_matches` | Drop jobs matching fewer of your skills |
| `skip_if_max_experience_below` | Drop junior jobs (experience range tops out below this) |
| `gig_keywords` / `gig_title_keywords` / `gig_ignore_phrases` | Gig-signal detection (side hunt) |
| `require_gig_keywords` | Keep only jobs with a gig signal |
| `weights` | Score weights: `skills`, `title`, `experience`, `remote`, `gig` |
| `min_score` | Minimum score to appear in results |
| `max_results` | Max jobs per run (best first); the rest aren't marked seen and show up later |
| `apply.max_per_run` / `max_per_day` | Caps for CLI and agent auto-apply |
| `apply.skip_questionnaires` | Leave jobs with recruiter questions to you |
| `outreach.name` / `subject` / `body` | Email template for the contact list's "Draft email" links |

## Privacy

Everything runs locally. These files are git-ignored and never leave your machine: your resume
(`*.pdf`), Naukri login (`.env`, readable only by you), your configs, the saved browser session
and job history (`data/`), and reports (`output/`).

## Troubleshooting

| Problem | Fix |
|---|---|
| `run.sh: command not found` | Run it as `./run.sh` from the project folder |
| `Permission denied` | `chmod +x run.sh` |
| `python: command not found` | Not needed; `./run.sh` uses `python3` and its own `.venv` |
| Searches return 0 jobs / "Access Denied" | Keep `headless: false`; install Google Chrome |
| Login asks for OTP/captcha | Complete it in the Chrome window; the session is then saved |
| Too many irrelevant jobs | Raise `min_score`, add `exclude_title_keywords`, tune `skills` |

## Project layout

| Path | Contents |
|---|---|
| `run.sh` | One-command entry point: environment, setup wizard, then `hunt.py` |
| `hunt.py` | CLI, search pipeline, reports |
| `setup_wizard.py` | First-run setup (configs, resume, experience, roles, login) |
| `naukri.py` | Browser automation: search, job details, login, apply |
| `matcher.py` | Resume parsing, gig-signal detection and scoring |
| `contacts.py` | Contact list: emails/phones from job posts, company links, email drafts |
| `mcp_server.py` | MCP server for AI agents |
| `examples/` | Config templates for the regular and side-gig hunts |
| `.cursor/` | Cursor MCP registration and agent rule |

## Disclaimer

This is an unofficial personal-productivity tool, not affiliated with Naukri.com / Info Edge.
Naukri's terms don't allow automated use; searching with polite delays is low risk, but heavy
auto-applying can get an account flagged. Keep the caps low, review jobs before applying, and use it
at your own risk.

## License

[MIT](LICENSE)

Maintenance

ActivityMaintained
ResponsivenessNo issues