JobShield

Inspiration

Job searching is already difficult for students and new graduates. Applicants spend hours tailoring resumes, completing assessments, and preparing for interviews while also having to determine whether every opportunity is legitimate.

During my own job search, I noticed that suspicious postings are not always obvious. Some contain unrealistic salaries, vague company descriptions, copied job requirements, unusual contact methods, or requests to continue conversations outside trusted platforms. At the same time, legitimate startups and smaller companies may also have incomplete or unconventional postings.

This makes it difficult to evaluate a listing using simple rules alone.

I built JobShield to explore whether machine learning could help job seekers recognize unusual patterns in job postings while communicating uncertainty responsibly.

Instead of declaring that a job is real or fake, JobShield provides explainable signals that help users decide when further verification may be necessary.

What it does

JobShield is an explainable machine-learning platform that analyzes job postings for potentially suspicious patterns.

A user can either:

  1. Paste a job posting into the web application.
  2. Analyze the current job listing through the JobShield Chrome extension.

The platform evaluates several independent signals:

  • Fraud-related language and metadata patterns
  • Missing or incomplete company information
  • Unusual or incorrectly formatted salary ranges
  • Duplicate or highly similar job descriptions
  • Repeatedly observed postings

Results are presented using cautious labels such as:

  • Low model risk
  • Some unusual signals
  • Review recommended
  • Insufficient information

Each prediction includes an explanation of the signals that influenced it. JobShield does not claim that a company or recruiter is fraudulent. Its purpose is to help users recognize when they should independently verify an opportunity before sharing personal information.

How I built it

I built JobShield as a complete machine-learning product rather than an application that sends job descriptions to an LLM.

The project is organized as a monorepo containing:

  • A Python machine-learning pipeline
  • A FastAPI prediction service
  • A Next.js web dashboard
  • A Chrome Manifest V3 extension
  • Shared types, tests, reports, and model artifacts

Machine-learning pipeline

The fraud-classification pipeline processes job-description text alongside structured listing metadata.

The data-preparation workflow:

  1. Loads the job-posting dataset.
  2. Cleans HTML and inconsistent whitespace.
  3. Handles missing fields.
  4. Combines relevant text fields.
  5. Removes duplicate records.
  6. Creates stratified training, validation, and test splits.
  7. Saves reproducible processed datasets and data-quality reports.

I trained and compared two primary approaches:

  • TF-IDF with Logistic Regression
  • TF-IDF with XGBoost

The system selects the final model using validation precision-recall area under the curve rather than accuracy alone.

This was important because fraudulent postings represent only a small portion of the dataset. A model could classify every posting as legitimate and still achieve high accuracy.

For this imbalanced classification problem, I focused on:

[ \text{Precision} = \frac{TP}{TP + FP} ]

[ \text{Recall} = \frac{TP}{TP + FN} ]

Precision measures how often flagged postings are actually fraudulent, while recall measures how many fraudulent postings the model successfully identifies.

The trained preprocessing and classification pipeline is saved as a reusable model artifact and loaded by the API during inference.

Explainability

JobShield returns more than a probability.

The application identifies contributing signals such as:

  • Missing company profile
  • Vague job requirements
  • Unusual salary formatting
  • Suspicious contact or payment language
  • Similarity to previously observed postings

These explanations help users understand why the model produced its result instead of presenting a score without context.

Salary analysis

The salary module parses formats such as:

  • $60,000–$80,000 per year
  • $35 per hour
  • 70k CAD

It normalizes hourly and annual values, checks for malformed ranges, and identifies unusually high or low compensation.

Salary anomalies are displayed separately because an unusual salary does not prove that a posting is fraudulent.

Duplicate detection

JobShield creates normalized posting fingerprints and sentence embeddings for job descriptions.

Cosine similarity is used to identify:

  • Exact duplicates
  • Near-duplicate listings
  • Shared templates
  • Repeatedly observed descriptions

A repeated posting is not automatically labelled as a ghost job. The interface only reports how similar the content is and how often it has been observed.

Backend

I built the backend using FastAPI.

It provides endpoints for:

  • Individual analysis
  • Batch analysis
  • Analysis history
  • User feedback
  • Model information
  • Health checks

The backend also includes input validation, error handling, structured responses, model versioning, and a SQLite fallback for local development.

Web application

I built the frontend using Next.js, TypeScript, and Tailwind CSS.

It includes:

  • A landing page
  • Job-analysis form
  • Explainable results dashboard
  • Analysis history
  • Methodology page
  • Model-performance dashboard
  • Synthetic demonstration listings

The technical dashboard displays model metrics and evaluation results so users can understand how the system was tested.

Chrome extension

I also built a Chrome Manifest V3 extension that opens JobShield in the browser side panel.

It attempts to extract:

  • Job title
  • Company
  • Location
  • Salary
  • Description
  • Requirements
  • Company profile

The extension first looks for structured JobPosting JSON-LD data and then uses website-specific or generic extraction logic.

Before anything is analyzed, the extracted fields are shown to the user for review. The extension does not continuously monitor browsing activity or automatically transmit page content.

Challenges I faced

Class imbalance

One of the biggest modelling challenges was that fraudulent postings are much less common than legitimate ones.

Accuracy was therefore not meaningful on its own. I used class weighting and focused on precision, recall, F1 score, and PR-AUC.

This required considering the real cost of each type of error:

  • A false negative could fail to warn someone about a suspicious posting.
  • A false positive could unfairly make a legitimate opportunity appear unsafe.

Because of this trade-off, JobShield avoids definitive labels and uses softer risk categories.

Data leakage

Duplicate or nearly identical postings can appear multiple times within a dataset.

If similar postings are placed in both the training and test sets, the model may appear more accurate because it has already seen almost identical content.

I added duplicate removal, normalized fingerprints, and similarity checks to reduce this risk. A future improvement would group all related postings before creating the dataset splits.

Communicating uncertainty

A machine-learning score can easily appear more certain than it actually is.

I did not want users to interpret a high score as proof that a company was committing fraud. The interface therefore separates fraud indicators, salary anomalies, and duplicate activity instead of combining everything into one accusation.

Every report includes limitations and encourages independent verification.

Limited and outdated labelled data

Publicly available labelled job-fraud datasets are limited. The main EMSCAD dataset is useful, but its postings are older and may not fully represent modern scams.

I designed the system so the model can be retrained as newer and more diverse data becomes available.

During initial development, I used a synthetic EMSCAD-shaped bootstrap dataset to validate the full training and deployment pipeline. I do not treat those synthetic results as production-quality evidence. The next evaluation step is to retrain and test the model using the official dataset and a separate modern validation set.

Browser extraction

Job websites use different layouts, dynamic rendering, and inconsistent metadata.

Creating one extractor that works everywhere was unrealistic, so I designed multiple extraction layers:

  1. Structured JSON-LD extraction
  2. Site-specific adapters
  3. Generic semantic extraction
  4. Manual paste fallback

This allows the product to remain usable even when automatic extraction fails.

What I learned

The biggest lesson was that building a machine-learning product involves much more than training a model.

Through JobShield, I learned how to:

  • Create a reproducible data-processing pipeline
  • Evaluate imbalanced classification problems
  • Compare baseline and improved models
  • Detect and reduce possible data leakage
  • Serve a trained model through FastAPI
  • Translate model outputs into understandable explanations
  • Connect machine learning to a frontend and browser extension
  • Design for failures, missing fields, and uncertain predictions
  • Communicate ethical limitations clearly

I also learned that explainability is not only a technical feature. It is part of the user experience.

A probability alone does not help someone decide what to do. Users need to understand which signals were detected, how confident the model is, and where it may be wrong.

Accomplishments I am proud of

I am proud that JobShield is an end-to-end system rather than a model contained inside a notebook.

The completed project includes:

  • A reproducible training pipeline
  • Logistic Regression and XGBoost model comparison
  • Saved and versioned model artifacts
  • Explainable predictions
  • Salary anomaly analysis
  • Duplicate-content detection
  • A FastAPI backend
  • A responsive Next.js dashboard
  • A Chrome side-panel extension
  • Persistent analysis history
  • Synthetic demonstration listings
  • Automated ML, API, web, and extension tests

Most importantly, I designed the system around responsible communication. JobShield helps users investigate job postings without pretending that a machine-learning model can determine an employer’s intentions with certainty.

What’s next for JobShield

The next step is to retrain and evaluate JobShield using the official EMSCAD dataset and a separate set of more recent job postings.

Future improvements include:

  • Validation using modern job listings
  • Canadian occupation and salary benchmarks
  • Improved duplicate-cluster detection
  • Detection of changing company names and contact information
  • Multilingual job-posting support
  • Model-drift monitoring
  • User-submitted feedback for model improvement
  • Additional browser extraction adapters
  • A publicly available Chrome extension
  • On-device or privacy-preserving analysis options

The long-term goal of JobShield is not to replace human judgment or automatically decide which opportunities are legitimate.

Its goal is to give job seekers clearer, explainable signals before they share sensitive information, communicate with a recruiter, or proceed with an application.

Built With

Share this project:

Updates