A full-stack NLP project that classifies news articles as REAL or FAKE using a Scikit-Learn text classifier, served through a Flask REST API backend and a Streamlit frontend.
Author: Ayush Khetan
Inspired by muqadasejaz/Fake-News-Detection, rebuilt with a proper client-server architecture (Flask API + Streamlit UI) and an optional Sentence-Transformer embedding mode.
- Paste any news article text and get an instant REAL / FAKE prediction with a confidence score.
- Two selectable feature-extraction pipelines:
- TF-IDF +
PassiveAggressiveClassifier(fast, classic baseline, default) - Sentence-Transformers (
all-MiniLM-L6-v2) +LogisticRegression(semantic embeddings, usually more robust to paraphrasing)
- TF-IDF +
- Clean separation of concerns:
src/(ML),backend/(API),frontend/(UI) - Works out of the box with a small synthetic dataset for testing, and upgrades seamlessly to the full Kaggle dataset for real accuracy.
┌────────────────────┐ HTTP (JSON) ┌────────────────────┐
│ Streamlit Frontend │ ───────────────────────► │ Flask Backend │
│ (frontend/ │ POST /predict {text} │ (backend/app.py) │
│ streamlit_app.py) │ ◄─────────────────────── │ │
└────────────────────┘ {label, confidence} └──────────┬────────────┘
│
▼
┌────────────────────┐
│ src/predict.py │
│ loads model from │
│ models/*.pkl │
└──────────┬────────────┘
│
▼
┌────────────────────┐
│ src/train_model.py │
│ TF-IDF / SBERT + │
│ classifier │
└────────────────────┘
| Layer | Technology |
|---|---|
| Language | Python 3.10+ |
| ML / Vectorization | Scikit-Learn, TF-IDF, Sentence-Transformers |
| Backend API | Flask, Flask-CORS |
| Frontend | Streamlit |
| Data | Pandas, NumPy |
| Model persistence | Joblib |
fake-news-detection/
├── README.md
├── requirements.txt
├── .gitignore
├── data/
│ └── README.md # dataset download instructions
├── models/ # trained model files (generated, gitignored)
├── src/
│ ├── preprocessing.py # text cleaning shared by train + inference
│ ├── generate_sample_data.py # creates tiny test dataset
│ ├── train_model.py # trains TF-IDF or SBERT model
│ └── predict.py # loads model, exposes predict()
├── backend/
│ └── app.py # Flask REST API
└── frontend/
└── streamlit_app.py # Streamlit UI
git clone <your-repo-url>
cd fake-news-detection
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtOption A — real dataset (recommended for a real model):
Download the Fake and Real News Dataset
from Kaggle and place Fake.csv and True.csv inside data/.
Option B — quick test with synthetic data:
python src/generate_sample_data.py# TF-IDF (default, fast)
python src/train_model.py
# OR Sentence-Transformer embeddings
python src/train_model.py --embedding sbertThis prints accuracy, a classification report, and a confusion matrix, then
saves the model to models/.
python backend/app.pyThe API will be live at http://localhost:5000.
Endpoints:
| Method | Route | Body | Response |
|---|---|---|---|
| GET | /health |
– | {"status": "ok"} |
| POST | /predict |
{"text": "<article>"} |
{"label": "REAL"/"FAKE", "confidence": 0.87, "embedding": "tfidf"} |
In a separate terminal:
streamlit run frontend/streamlit_app.pyOpen the URL Streamlit prints (usually http://localhost:8501), paste an
article, and click Analyze.
- Preprocessing (
src/preprocessing.py): lowercasing, URL/HTML stripping, punctuation/digit removal, stopword removal. - Feature extraction:
- TF-IDF: converts cleaned text into weighted unigram/bigram vectors.
- SBERT: encodes cleaned text into 384-dim dense semantic embeddings
using
all-MiniLM-L6-v2.
- Classification:
- TF-IDF →
PassiveAggressiveClassifier(fast online linear classifier, well suited to high-dimensional sparse TF-IDF vectors). - SBERT →
LogisticRegressionon dense embeddings.
- TF-IDF →
- Inference: the same cleaning function is applied at prediction time, then the saved vectorizer/embedder + classifier produce a label and a confidence score, returned by the Flask API and rendered by Streamlit.
After training, check the console output for:
- Accuracy
- Precision / Recall / F1 (per class)
- Confusion matrix
On the full Kaggle dataset, this pipeline typically reaches 90%+ accuracy with TF-IDF and comparable or better results with SBERT embeddings, depending on preprocessing and hyperparameters.
- Fine-tune a transformer (e.g. DistilBERT) end-to-end for higher accuracy.
- Add source/URL credibility signals alongside text content.
- Add explainability (e.g. highlight influential words with LIME/SHAP).
- Dockerize backend + frontend for one-command deployment.
- Add authentication and rate limiting to the API for public deployment.
This is an educational/demo project. Predictions are based on writing style and linguistic patterns learned from a training dataset — they are not a substitute for fact-checking or verified journalism.
MIT License — free to use and modify.
Built by Ayush Khetan