Building an Automated Naukri Job Alert System with Python
How to build a custom Naukri job monitoring system that filters by salary, location, and skills — and sends instant alerts when relevant jobs post.
The actor referenced in this article is live on Apify. Pay only for results delivered.
Naukri’s built-in job alerts work but are limited — you cannot filter by minimum salary threshold, combine multiple skill requirements with AND logic, or receive alerts only for companies above a certain funding stage or size. Building a custom alert system gives you full control over the filtering logic.
TL;DR: Build a custom Naukri alert system beyond the platform’s built-in filters: fetch jobs via the Apify Naukri Scraper, apply multi-dimensional filters (minimum salary LPA, experience range, required skills with AND logic, work mode), score matches by preferred companies and skills, and send a formatted daily email digest. Typical output: 15-40 curated matches per day for a narrow profile instead of hours of manual browsing.
This guide shows how to build a Naukri job monitoring system that runs on a schedule, applies custom filters, and delivers a curated daily digest.
What the System Does
- Pulls the latest job postings from Naukri for your target keywords
- Applies multi-dimensional filters (salary range, experience, location, company size)
- Scores and ranks postings by match quality
- Sends a formatted digest email with the top matches
Step 1: Data Collection
from apify_client import ApifyClient
from datetime import datetime
client = ApifyClient('YOUR_API_TOKEN')
def fetch_naukri_jobs(keywords: list[str], location: str = None, max_jobs: int = 100) -> list[dict]:
"""Fetch recent Naukri jobs for multiple keyword searches."""
all_jobs = []
for keyword in keywords:
run = client.actor('themineworks/naukri-jobs').call(run_input={
'searchKeywords': keyword,
'location': location,
'maxJobs': max_jobs,
'includeJobDescription': True,
'sortBy': 'date', # Most recent first
})
jobs = list(client.dataset(run['defaultDatasetId']).iterate_items())
for job in jobs:
job['_search_keyword'] = keyword
all_jobs.extend(jobs)
# Deduplicate by job ID
seen = set()
deduped = []
for job in all_jobs:
if job['jobId'] not in seen:
seen.add(job['jobId'])
deduped.append(job)
return deduped
Step 2: Custom Filtering
def parse_salary_range(salary_str: str) -> tuple[int, int] | None:
"""Parse '₹15-25 Lacs PA' → (1500000, 2500000)"""
if not salary_str:
return None
import re
# Match patterns like "15-25 Lacs", "15L-25L", "15 - 25 LPA"
match = re.search(r'(\d+(?:\.\d+)?)\s*[-–]\s*(\d+(?:\.\d+)?)\s*(?:L|Lac|LPA|lakh)', salary_str, re.IGNORECASE)
if match:
min_l = float(match.group(1))
max_l = float(match.group(2))
return (int(min_l * 100000), int(max_l * 100000))
return None
def filter_jobs(jobs: list[dict], criteria: dict) -> list[dict]:
"""Apply filtering criteria to job list."""
filtered = []
for job in jobs:
# Salary filter
if criteria.get('min_salary_lpa'):
salary = parse_salary_range(job.get('salaryRange', ''))
if salary:
max_salary_lpa = salary[1] / 100000
if max_salary_lpa < criteria['min_salary_lpa']:
continue
# Experience filter
exp = job.get('experience', {})
if criteria.get('max_experience_years') and exp.get('max'):
if exp['max'] > criteria['max_experience_years']:
continue
if criteria.get('min_experience_years') and exp.get('min'):
if exp['min'] < criteria['min_experience_years']:
continue
# Required skills filter (AND logic — all must be present)
if criteria.get('required_skills'):
desc = (job.get('description', '') + ' ' + job.get('skills', '')).lower()
if not all(skill.lower() in desc for skill in criteria['required_skills']):
continue
# Excluded keywords
if criteria.get('excluded_keywords'):
title = job.get('title', '').lower()
if any(kw.lower() in title for kw in criteria['excluded_keywords']):
continue
# Work mode filter
if criteria.get('work_modes'):
job_mode = job.get('workMode', '').lower()
if not any(mode.lower() in job_mode for mode in criteria['work_modes']):
continue
filtered.append(job)
return filtered
Step 3: Match Scoring
Rank filtered jobs by how well they match your ideal profile:
def score_job(job: dict, preferences: dict) -> float:
"""Score a job 0.0-1.0 based on match to preferences."""
score = 0.5 # Baseline
desc = (job.get('description', '') + ' ' + job.get('skills', '')).lower()
# Bonus for preferred skills
for skill in preferences.get('preferred_skills', []):
if skill.lower() in desc:
score += 0.05
# Bonus for preferred companies
company = job.get('company', '').lower()
for pref_company in preferences.get('preferred_companies', []):
if pref_company.lower() in company:
score += 0.15
# Bonus for salary disclosure
if job.get('salaryRange'):
score += 0.05
# Bonus for application recency
posted_days = job.get('daysAgo', 30)
if posted_days <= 1:
score += 0.1
elif posted_days <= 3:
score += 0.05
return min(1.0, score)
Step 4: Digest Email
def format_digest_email(jobs: list[dict], date: str) -> str:
if not jobs:
return f"No new matching jobs found on {date}."
lines = [f"📊 Naukri Job Digest — {date}", f"Found {len(jobs)} matching positions\n", "─" * 50]
for i, job in enumerate(jobs[:15], 1):
salary = job.get('salaryRange', 'Not disclosed')
location = job.get('location', 'Not specified')
posted = f"{job.get('daysAgo', '?')} day(s) ago"
score = job.get('_match_score', 0)
lines.extend([
f"\n{i}. {job['title']}",
f" Company: {job.get('company', 'Unknown')}",
f" Salary: {salary}",
f" Location: {location}",
f" Posted: {posted}",
f" Match: {'⭐' * round(score * 5)}",
f" URL: {job.get('url', '')}",
])
return '\n'.join(lines)
# Send email (using any SMTP provider)
import smtplib
from email.mime.text import MIMEText
def send_digest(body: str, recipient: str):
msg = MIMEText(body)
msg['Subject'] = f"Naukri Digest — {datetime.now().strftime('%d %b %Y')}"
msg['From'] = 'alerts@yourdomain.com'
msg['To'] = recipient
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
smtp.starttls()
smtp.login('your_email', 'your_app_password')
smtp.send_message(msg)
Step 5: Putting It Together
import schedule
import time
MY_CRITERIA = {
'min_salary_lpa': 20,
'min_experience_years': 3,
'max_experience_years': 7,
'required_skills': ['python'],
'excluded_keywords': ['intern', 'trainee', 'fresher'],
'work_modes': ['hybrid', 'remote', 'wfh'],
}
MY_PREFERENCES = {
'preferred_skills': ['fastapi', 'aws', 'kubernetes', 'llm', 'langchain'],
'preferred_companies': ['google', 'microsoft', 'amazon', 'flipkart', 'razorpay'],
}
def daily_job_check():
keywords = ['senior python developer', 'python backend engineer', 'python ml engineer']
jobs = fetch_naukri_jobs(keywords, location='Bangalore', max_jobs=200)
filtered = filter_jobs(jobs, MY_CRITERIA)
for job in filtered:
job['_match_score'] = score_job(job, MY_PREFERENCES)
ranked = sorted(filtered, key=lambda j: j['_match_score'], reverse=True)
digest = format_digest_email(ranked, datetime.now().strftime('%d %b %Y'))
send_digest(digest, 'your-email@example.com')
print(f"Daily check: {len(jobs)} total → {len(filtered)} matches → digest sent")
schedule.every().day.at('07:30').do(daily_job_check)
while True:
schedule.run_pending()
time.sleep(60)
The system typically finds 15-40 matching jobs per day for a narrowly specified profile in a major city. Compared to manual Naukri browsing, this takes 30 seconds to review instead of 30 minutes.
Frequently Asked Questions
What custom filters can you apply to Naukri job alerts that the built-in system does not support?
Naukri’s built-in alerts filter by keyword, location, experience, and industry — but lack: minimum salary thresholds (you can set salary range but not a hard minimum), AND-logic for multiple required skills (built-in uses OR), specific company inclusion/exclusion lists, work-mode filtering (remote/hybrid/office), and match-quality scoring. A custom Python system using the Apify Naukri scraper can apply all of these simultaneously, plus rank results by weighted criteria.
How do you parse salary ranges from Naukri job postings in Python?
Naukri salary data comes as strings like “8-12 Lacs PA” or “Not Disclosed”. Use a regex pattern to extract min/max: re.search(r'(\d+\.?\d*)\s*-\s*(\d+\.?\d*)\s*Lacs?', salary_str). Convert to a standard unit (LPA as float). Handle edge cases: “15+ Lacs” (set min=15, max=None), “Not Disclosed” (set both to None), and “20,000-30,000 per month” (convert to annual LPA). Filter by salary_min >= your_threshold and skip postings where salary is None if you have strict requirements.
How does AND-logic skill filtering work for Naukri job matching?
Naukri’s search returns jobs matching any of your keywords (OR logic). To apply AND logic, fetch a broader result set and filter client-side: download all postings for your primary keyword, then check each job’s description and title for the presence of all required skills. For example, to find “Python AND Kubernetes AND AWS”, fetch Python jobs, then filter to those containing both “kubernetes” or “k8s” and “aws” or “amazon web services” in the combined title+description text. Case-insensitive regex matching handles variations.
How do you score and rank job postings by match quality?
Assign point weights to criteria: preferred company match (+3), primary skill in title (+2), secondary skill in description (+1), salary above threshold (+2), work mode preference match (+1). Sum the points for each job and sort descending. A job at a preferred company mentioning your primary skill in the title with salary above your floor scores highest. This ranking surfaces your best 5-10 matches at the top rather than requiring you to scan all 40 daily results.
How much does it cost to run an automated Naukri job monitoring system?
The Apify Naukri Jobs scraper under PPE billing costs approximately $0.005-0.01 per job listing. Running daily alerts for 1-2 keyword profiles generating 50-100 results costs roughly $0.15-0.30/day — under $10/month. If you add Claude Haiku to score match quality (rather than rule-based scoring), add another $0.02-0.05/day. Total: under $15/month for a custom daily alert system that outperforms Naukri’s built-in alerts significantly.
Try the scraper referenced in this article — live on Apify, pay only for results.
Open naukri-jobs on Apify →How to Scrape AmbitionBox Company Reviews and Ratings
AmbitionBox is India largest employer review platform with 300,000 companies. Learn how to pull ratings, review counts, salary data, and dimension scores as structured JSON without any official API.
AliExpress Product Data API: Prices, Ratings, and Orders in Python
AliExpress affiliate API has restricted coverage. Learn how to scrape AliExpress product listings for prices, ratings, order counts, and seller data as structured JSON — no affiliate approval needed.
ClinicalTrials.gov API v2: How to Search 500,000 Studies and Track Trial Status
ClinicalTrials.gov upgraded to a v2 REST API in 2024. Here is how to use it, what changed from v1, and how to build automated trial monitoring pipelines in Python.