Build an AI Phishing URL Detector

Train a machine learning model to detect phishing URLs with 85%+ accuracy.

Introduction

30 Second Summary

You get a text with a link asking you to verify your bank account. The URL looks almost right, but something feels off. Cybersecurity teams face this same challenge thousands of times a day, except they use AI to make the call in milliseconds.

In this project, you will train a machine learning model to detect phishing URLs and build an interactive scanner that gives you an instant verdict on any link you paste in.

What You'll Build

Paste any URL into your terminal and watch your AI classify it as PHISHING or SAFE in under a second, complete with a confidence percentage telling you how sure it is.

By the end of this project, you'll have:

  • A working phishing URL scanner where you paste any link and instantly see a PHISHING or SAFE verdict with a confidence score you trained yourself.
  • A feature importance ranking revealing which URL characteristics (length, IP addresses, suspicious keywords) are the strongest phishing signals.
  • A full classification report showing you exactly how many phishing URLs your AI catches versus how many slip through undetected.
  • Secret Mission: Add risk levels (HIGH/MEDIUM/LOW) and human-readable explanations showing exactly which features triggered the alert.

Are there any prerequisites?

None. This project includes full setup instructions for Python, VS Code, and all required libraries. No prior experience with machine learning or cybersecurity is needed.

Before We Start

Before We Start...

Before we dive in, let's lock in what you're about to build and why it matters.

Set Up Your Python Environment

Building an AI-powered phishing detector requires a few foundational tools. You need a programming language that supports machine learning, a code editor to write in, and the dataset your AI will learn from.

In this step, you will install Python 3.13 and VS Code, create a project folder, install the machine learning libraries, and download a real cybersecurity research dataset.

In this step, get ready to:
  • Install Python 3.13 and VS Code on your machine.
  • Create a project folder and install machine learning libraries.
  • Download and verify a phishing URL dataset with 235,000+ labeled URLs.
Install Python and VS Code

Python is the programming language your AI model will be written in. VS Code is the code editor where you will write and run your scripts.

  • Open your browser and go to python.org/downloads.
  • Click the download button for Python 3.13.
  • Run the installer once it downloads.
  • On the first installer screen, check the box labeled Add python.exe to PATH. This is critical for running Python from the terminal later.
  • Click Install Now and wait for the installation to finish.

Why does PATH matter?

Adding Python to your PATH tells Windows where to find the python command. Without it, your terminal will not recognize python as a valid command and every step after this will fail.

  • Confirm Python installed correctly by checking its version. Open your Start menu, type cmd, and press Enter to open a Command Prompt.
  • Check your Python version by running this command:
python --version

✔️ I see Python 3.13

You should see something like Python 3.13.x printed back. Python is installed and ready to go.

ⓧ I see an older version

If you see a version lower than 3.13 (like 3.11 or 3.9), you have an older Python installation taking priority.

  • Open Settings, then Apps, then Installed apps.
  • Find the older Python version and uninstall it.
  • Re-run the Python 3.13 installer from python.org/downloads, making sure to check Add python.exe to PATH.
  • Close and reopen your Command Prompt, then run python --version again.

ⓧ 'python' is not recognized

This means Python was not added to your PATH during installation.

  • Re-run the Python installer you downloaded.
  • Select Modify.
  • On the Advanced Options screen, check the box for Add Python to environment variables.
  • Click Install.
  • Close your Command Prompt completely and reopen it, then run python --version again.
  • Now install VS Code. Open your browser and go to code.visualstudio.com.
  • Click the download button for Windows and run the installer.
  • Accept the defaults and complete the installation.
  • Press the Windows key to open your search bar.
  • Type Visual Studio Code and press Enter to open it.
  • In VS Code, open a terminal by clicking Terminal in the top menu bar, then clicking New Terminal.

A terminal panel appears at the bottom of VS Code. This is where you will run all your commands for the rest of the project.

Terminal not opening?

If you do not see the Terminal option in the menu, try the keyboard shortcut Ctrl+` (that is the backtick key, above Tab). If VS Code opened to a Welcome tab, close it and try again.

Help me open the terminal in VS Code.

Create project folder and install libraries

You need a dedicated folder for your phishing detector project files, plus two Python libraries that provide machine learning and data analysis tools.

  • Move to your Desktop by running this command in the VS Code terminal:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir phishing-detector
cd phishing-detector

Your terminal prompt now shows phishing-detector, confirming the folder was created and you are inside it.

  • Install the required Python libraries by running:
pip install scikit-learn pandas

What are these libraries?

scikit-learn is a machine learning library. It provides the algorithms (including Random Forest) that your phishing detector will use to classify URLs.

pandas is a data analysis library. It loads and processes the dataset of 235,000+ URLs so scikit-learn can learn from them.

You should see download progress followed by Successfully installed at the end of the output. This confirms both packages are ready.

Seeing 'pip is not recognized'?

This means Python's Scripts folder was not added to PATH. Close VS Code, re-run the Python installer, select Modify, and ensure Add Python to environment variables is checked on the Advanced Options screen. Then reopen VS Code and try again.

Help me fix the pip not recognized error on Windows.

Download the phishing dataset

Your AI needs data to learn from. You will download a real cybersecurity research dataset containing 235,795 labeled URLs from the UCI Machine Learning Repository.

  • Open your browser and go to the dataset page: UCI PhiUSIIL Phishing URL Dataset.
  • Click the Download (14.7 MB) button to get the ZIP file.
  • Once downloaded, find the ZIP file in your Downloads folder.
  • Right-click the ZIP file and select Extract All, then click Extract.
  • Inside the extracted folder, find the file named PhiUSIIL_Phishing_URL_Dataset.csv.
  • Copy this file into your phishing-detector folder on the Desktop.

Fastest way to copy the file

Open two File Explorer windows side by side. In one, navigate to the extracted ZIP contents. In the other, open Desktop > phishing-detector. Drag the CSV file across.

  • Before you run the verification command, predict: what shape do you think this dataset will have? How many rows and columns?
  • Verify the dataset loads correctly by running this command in your VS Code terminal:
python -c "import pandas; print(pandas.read_csv('PhiUSIIL_Phishing_URL_Dataset.csv').shape)"

You should see (235795, 56) printed back. This confirms your dataset has 235,795 URLs across 56 columns of data.

Seeing a FileNotFoundError?

This means the CSV file is not in your current folder. Make sure your terminal is inside the phishing-detector folder (check the prompt) and that you copied PhiUSIIL_Phishing_URL_Dataset.csv into it (not a subfolder).

Run dir to list the files in your current folder. You should see PhiUSIIL_Phishing_URL_Dataset.csv in the output.

Help me find and move the dataset file to the right folder.

Your environment is ready and loaded with real cybersecurity data. Next up, you will explore this dataset and see what real phishing URLs look like compared to legitimate ones.

Load and Explore the Phishing Dataset

Your Python environment is ready with scikit-learn and pandas installed, and the phishing dataset sitting in your project folder. Now it's time to look at the data your AI will learn from.

Before building a machine learning model, you need to understand what it will be working with. Seeing real phishing URLs next to legitimate ones reveals the structural patterns your AI can learn to detect.

In this step, get ready to:
  • Load the phishing dataset and print basic statistics.
  • Display sample phishing and legitimate URLs side by side.
Create the Python script and load the data

The dataset contains 235,000+ URLs, each labeled as phishing or legitimate. Loading it into a pandas DataFrame lets you inspect the shape of the data and see how many of each type exist.

  • In the VS Code Explorer sidebar, right-click the phishing-detector folder and select New File.
  • Name the file phishing_detector.py and press Enter.
  • Paste the following code into the new file:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
import re

# ============================================================
# LOAD AND EXPLORE THE DATASET
# ============================================================

print("=" * 50)
print("AI-POWERED PHISHING URL DETECTOR")
print("=" * 50)

# Load the dataset
df = pd.read_csv("PhiUSIIL_Phishing_URL_Dataset.csv")

print(f"\nDataset loaded: {len(df):,} URLs")
print(f"Columns: {len(df.columns)}")

# Show label distribution
print(f"\nLabel distribution:")
print(f"  Legitimate (1): {len(df[df['label'] == 1]):,}")
print(f"  Phishing (0):   {len(df[df['label'] == 0]):,}")

What does this code do?

  • The imports bring in all the libraries you will use across the project: pandas for data handling, scikit-learn modules for machine learning, and re for regular expressions.
  • pd.read_csv() loads the entire CSV file into a DataFrame called df.
  • The label distribution shows how many URLs are legitimate (label 1) vs phishing (label 0). This tells you whether the dataset is balanced or skewed.
  • Save phishing_detector.py by pressing Ctrl+S.
  • Run the script by entering this command in your terminal:
python phishing_detector.py

You should see the header banner, a line showing 235,795 URLs loaded with 56 columns, and the label distribution showing roughly 134,850 legitimate and 100,945 phishing URLs.

Seeing a FileNotFoundError?

Make sure PhiUSIIL_Phishing_URL_Dataset.csv is inside the phishing-detector folder, not in a subfolder from the ZIP extraction.

Also confirm your terminal is in the phishing-detector directory. You can check by running cd which prints your current path.

Help me debug a FileNotFoundError when loading my CSV in Python.

Display sample phishing vs legitimate URLs

Numbers alone do not tell the full story. Seeing actual URLs from each category reveals the patterns your AI will learn to spot.

  • In phishing_detector.py, add this code below the label distribution section:
# Show sample URLs
print("\n--- Sample LEGITIMATE URLs ---")
legit_sample = df[df['label'] == 1]['URL'].head(5)
for url in legit_sample:
    print(f"  {url}")

print("\n--- Sample PHISHING URLs ---")
phish_sample = df[df['label'] == 0]['URL'].head(5)
for url in phish_sample:
    print(f"  {url}")

What does this code do?

This filters the DataFrame by label and prints 5 sample URLs from each category. Legitimate URLs tend to be short, use HTTPS, and have recognizable domain names. Phishing URLs tend to be longer, may use IP addresses instead of domains, and often contain suspicious keywords like "login" or "verify".

  • Save phishing_detector.py by pressing Ctrl+S.

Before you run the script again, what do you think you will notice about the phishing URLs compared to the legitimate ones?

  • Run the script again:
python phishing_detector.py

Scroll to the bottom of the output. You should now see 5 legitimate URLs (short, clean domains) followed by 5 phishing URLs (often longer, with unusual characters or suspicious paths).

What patterns should I look for?

Compare the two groups. Phishing URLs often have these telltale signs: IP addresses instead of domain names, many hyphens or dots, suspicious path words like "login" or "account", and unusually long URLs designed to hide the real destination.

These are exactly the patterns you will teach your AI to detect in the next step.

Not seeing any URLs printed?

Make sure the sample URL code comes after the label distribution code, not inside it. Check that you have not accidentally indented the new code under a previous if or for block.

Help me figure out why my sample URLs are not printing.

✔️ Awesome, I've got everything!

Great. Double check you have saved phishing_detector.py and that both the dataset stats and the sample URLs appear when you run it.

ⓧ I'd like to double check the full code

Your phishing_detector.py should contain these two sections, in order:

  • Imports and dataset loading (the first chunk you pasted: imports, header prints, CSV load, stats, label distribution).
  • Sample URL display (the second chunk you added: printing 5 legitimate URLs then 5 phishing URLs).

Scroll up and confirm each section is present in your file, in that order, with no extra indentation.

You now have a clear picture of the data your AI will learn from: 235,000+ URLs split between phishing and legitimate, with visible structural differences. Next up, you will convert those URL patterns into numbers and train your first machine learning model.

Extract Features and Train the AI Model

In the previous step, you saw real phishing URLs side by side with legitimate ones. The structural differences were visible to your eyes.

Raw URL strings mean nothing to a machine learning algorithm. In this step, you'll convert each URL into 10 numbers that capture the security-relevant patterns you observed, then train a Random Forest classifier to learn which combinations signal phishing.

In this step, get ready to:
  • Extract 10 numeric features from each URL that capture phishing indicators.
  • Train a Random Forest model to classify URLs as phishing or legitimate.
Write the feature extraction code

A machine learning model needs numbers, not text. Feature engineering is the process of converting raw data into numeric values that represent meaningful patterns.

Each feature you extract captures a known phishing indicator. Phishing URLs tend to be longer, use IP addresses instead of domain names, and contain suspicious keywords like "login" or "verify".

  • In phishing_detector.py, scroll to the bottom of the file (after the phishing sample URLs print).
  • Add this feature extraction code below the last line:
# ============================================================
# EXTRACT FEATURES AND TRAIN THE MODEL
# ============================================================

print("\n" + "=" * 50)
print("FEATURE EXTRACTION")
print("=" * 50)

# Extract security-relevant features from URLs
features_df = pd.DataFrame({
    'url_length': df['URL'].str.len(),
    'domain_length': df['URL'].str.split('/').str[2].fillna('').str.len(),
    'num_dots': df['URL'].str.count(r'\.'),
    'num_hyphens': df['URL'].str.count('-'),
    'num_slashes': df['URL'].str.count('/'),
    'has_at_symbol': df['URL'].str.contains('@').astype(int),
    'has_ip': df['URL'].str.contains(
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
    ).astype(int),
    'is_https': df['URL'].str.startswith('https').astype(int),
    'num_digits': df['URL'].str.count(r'\d'),
    'has_suspicious_words': df['URL'].str.contains(
        r'login|verify|secure|account|update|confirm|bank|paypal|signin',
        case=False
    ).astype(int),
})

print(f"Extracted {len(features_df.columns)} features from each URL:")
for col in features_df.columns:
    print(f"  - {col}")

What does this code do?

Each line inside the DataFrame creates one numeric feature from the raw URL string using pandas vectorized string operations:

  • url_length and domain_length measure size. Phishing URLs are often abnormally long to hide their true destination.
  • has_ip checks whether the URL uses a raw IP address (like 192.168.1.1) instead of a real domain name.
  • has_suspicious_words flags URLs containing keywords attackers commonly use to trick victims, such as "login", "verify", or "bank".
  • is_https checks for HTTPS. Legitimate sites almost always use it, while many phishing sites skip it.
  • Save phishing_detector.py.
  • Run the script to confirm the features extract correctly:
python phishing_detector.py

You should see a new "FEATURE EXTRACTION" section listing all 10 features by name, after the sample URLs output.

Seeing a KeyError or column not found?

Make sure the DataFrame column name matches the dataset exactly. The URL column is uppercase: df['URL'] not df['url'].

If you see a SyntaxError, check that every line inside the DataFrame ends with a comma, and the closing }) is present at the bottom.

Help me debug my feature extraction code

Split data and train the Random Forest

With 235,000 URLs converted to numbers, your data is ready for the model. You need to hold back 20% of the data as a test set that the model never sees during training. This lets you measure how well it performs on URLs it has never encountered.

  • Add this code below the feature printing loop at the bottom of your file:
# Split into training and test sets
X = features_df
y = df['label']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

print(f"\nTraining set: {len(X_train):,} URLs")
print(f"Test set:     {len(X_test):,} URLs")

# Train the Random Forest model
print("\nTraining Random Forest model...")
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# Check accuracy
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.1%}")

What does this code do?

  • train_test_split splits the data: 80% for training the model, 20% for testing it. The stratify=y parameter ensures both sets keep the same ratio of phishing to legitimate URLs.
  • RandomForestClassifier(n_estimators=100) creates a forest of 100 decision trees. Each tree votes on whether a URL is phishing, and the majority wins.
  • model.fit() trains the model by showing it the training URLs and their correct labels. It learns which feature combinations predict phishing.
  • accuracy_score() compares the model's predictions on the test set against the real labels to see how often it guesses correctly.
  • Save phishing_detector.py.

Before you run this, what accuracy do you think the model will achieve? Remember, it only has 10 simple features extracted from the URL text alone.

  • Run the script to train the model and see the results:
python phishing_detector.py

At the bottom of the output, you should see "Model Accuracy:" followed by a percentage between 85% and 92%. That means the AI correctly classifies the vast majority of URLs using just 10 features.

Why is this impressive?

Your model achieves 85%+ accuracy using only properties of the URL string itself. It never visits the webpage, never checks domain registration, and never loads any content. It detects phishing purely from structural patterns in the text.

Model accuracy below 70%?

Check that y = df['label'] uses the correct column name (lowercase label). A wrong label column means the model is learning from garbage data.

Also confirm random_state=42 is set in both train_test_split and RandomForestClassifier. Without it, results vary on each run.

Help me figure out why my model accuracy is low

✔️ Awesome, I've got everything!

Great. Double check you have saved phishing_detector.py and the accuracy prints correctly at the bottom of your output.

ⓧ I'd like to double check the full code

Your file should have two main sections in this order:

  • The original "LOAD AND EXPLORE THE DATASET" section from Step 2 (imports, CSV loading, label distribution, sample URL printing).
  • The new "EXTRACT FEATURES AND TRAIN THE MODEL" section you just added (feature extraction into features_df, feature list printing, train/test split, model training, accuracy printing).

Scroll up through your code and confirm both sections are present in that order. The file should end with the print(f"\nModel Accuracy: {accuracy:.1%}") line.

Your AI can now tell phishing from legitimate URLs with impressive accuracy. But a single accuracy number hides something critical in cybersecurity. Next up, you'll expose exactly where the model fails and why that matters for real threat detection.

Expose the Model's Blind Spots

Your model printed an impressive accuracy score in the last step. In cybersecurity, that single number can be dangerously misleading.

A single phishing URL that slips through undetected can compromise an entire organization. You need to understand exactly where the model fails, not just its overall score.

In this step, get ready to:
  • Print the classification report showing precision and recall per class.
  • Display feature importance rankings to see which URL characteristics drive detection.
Print the classification report

Overall accuracy tells you how many URLs the model got right in total. It does not tell you how many phishing URLs specifically slipped through as "safe."

A classification report breaks performance down per class, showing precision (of the URLs flagged as phishing, how many actually were?) and recall (of all actual phishing URLs, how many did the model catch?).

  • In phishing_detector.py, scroll to the bottom of the file (after the line that prints Model Accuracy).
  • Add the following code at the end of the file:
# ============================================================
# DETAILED PERFORMANCE ANALYSIS
# ============================================================

print("\n" + "=" * 50)
print("DETAILED PERFORMANCE ANALYSIS")
print("=" * 50)

print("\nClassification Report:")
print(classification_report(
    y_test, y_pred,
    target_names=['PHISHING', 'LEGITIMATE']
))

What does this code do?

  • classification_report calculates precision, recall, and F1-score for each class separately.
  • target_names=['PHISHING', 'LEGITIMATE'] labels the output so you can read it at a glance instead of seeing raw 0/1 class numbers.
  • Low recall on PHISHING means missed threats getting through. Low precision means false alarms overwhelming analysts.

Before you run this, think: your model has ~85-92% overall accuracy. Do you think it catches phishing and legitimate URLs equally well, or does it favour one class?

  • Save phishing_detector.py.
  • Run the script to see the classification report by running:
python phishing_detector.py

Scroll to the DETAILED PERFORMANCE ANALYSIS section in the output. You should see a table with precision, recall, and F1-score for both PHISHING and LEGITIMATE classes.

What do precision and recall mean for security?

Look at the recall value for PHISHING. If it is 0.89, that means 11% of real phishing URLs were classified as safe and got through undetected. In a corporate inbox, that could mean dozens of successful attacks per day.

This is why accuracy alone is not enough in security. A model with 95% accuracy might still let 1 in 10 phishing URLs through.

Seeing a NameError for classification_report?

Check that your import line at the top of the file reads from sklearn.metrics import accuracy_score, classification_report. If classification_report is missing from that import, add it and re-run.

Help me debug a NameError in my phishing detector script.

Show feature importance rankings

Now you know how well the model performs per class. The next question is: which URL characteristics does it rely on most to make its decisions?

  • In phishing_detector.py, add the following code directly below the classification report block you just wrote:
# Feature importance
print("Feature Importance (what the AI looks for):")
importances = model.feature_importances_
for name, importance in sorted(
    zip(features_df.columns, importances),
    key=lambda x: x[1],
    reverse=True
):
    bar = "#" * int(importance * 50)
    print(f"  {name:25s} {importance:.3f} {bar}")

What does this code do?

  • model.feature_importances_ returns an array of scores showing how much each feature contributed to the model's decisions.
  • zip(features_df.columns, importances) pairs each feature name with its importance score.
  • The sorted(..., reverse=True) ranks features from most important to least, so the strongest phishing signals appear at the top.
  • The # bar gives a visual sense of each feature's relative weight.
  • Save phishing_detector.py.
  • Run the script again to see the full analysis:
python phishing_detector.py

Below the classification report, you should now see a ranked list of features with bar charts made of # characters. The feature at the top is the strongest phishing signal your model learned.

Why does feature importance matter?

Feature importance tells you what the AI actually learned about phishing. If url_length ranks highest, it means long URLs are the strongest phishing signal in this dataset. If has_ip ranks high, it means phishers commonly use raw IP addresses to disguise malicious domains.

This ranking also reveals if you have weak features that barely contribute. Those could be dropped or replaced with better ones to improve detection.

Not seeing feature importance output?

Make sure the feature importance code is outside and below the classification report's print() call, not accidentally indented inside it. Every line should start at column 0 (no leading spaces).

Help me figure out why my feature importance code is not printing.

✔️ Awesome, I've got everything!

Great. Double check you have saved phishing_detector.py and that your output includes the classification report and feature importance ranking.

ⓧ I'd like to double check the full code

Your phishing_detector.py should have these sections in order. Scroll through your file and confirm each is present:

  • Imports (pandas, sklearn, re) at the top.
  • LOAD AND EXPLORE THE DATASET section that prints dataset stats and sample URLs.
  • EXTRACT FEATURES AND TRAIN THE MODEL section that builds features_df, splits data, trains the model, and prints accuracy.
  • DETAILED PERFORMANCE ANALYSIS section that prints the classification report and feature importance ranking.

You now know exactly where your model succeeds and where it leaks. Next up, you will turn this analysis into a live tool where you can paste any URL and get an instant phishing verdict.

Build the Live URL Scanner

You now have a trained AI model that can distinguish phishing URLs from legitimate ones with high accuracy. But a model sitting inside a script that only evaluates test data is not a tool anyone can actually use.

In this step, you will turn your trained Random Forest model into an interactive command-line scanner. You will paste any URL and get an instant verdict with a confidence percentage.

In this step, get ready to:
  • Write a feature extraction function that converts a single URL into the same 10 features your model expects.
  • Build an interactive scanning loop that takes URLs, predicts phishing or safe, and prints a confidence score.
Write a single-URL feature extractor

During training, you used pandas vectorized string operations to extract features from 235,000 URLs at once. For a live scanner, you need a function that does the same extraction on one URL at a time.

Why a separate function?

The model expects input in the exact same shape as its training data: a DataFrame with 10 specific columns. If you pass raw URL text, the model has no idea what to do with it.

This function is the bridge between a human typing a URL and the AI making a prediction.

  • In phishing_detector.py, scroll to the very bottom of your file (after the feature importance loop).
  • Add the following code to define the live URL scanner section and the feature extraction function:
# ============================================================
# LIVE URL SCANNER
# ============================================================

def extract_url_features(url):
    """Extract the same features used during training from a single URL."""
    return pd.DataFrame([{
        'url_length': len(url),
        'domain_length': len(url.split('/')[2]) if len(url.split('/')) > 2 else 0,
        'num_dots': url.count('.'),
        'num_hyphens': url.count('-'),
        'num_slashes': url.count('/'),
        'has_at_symbol': int('@' in url),
        'has_ip': int(bool(re.search(
            r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', url
        ))),
        'is_https': int(url.startswith('https')),
        'num_digits': len(re.findall(r'\d', url)),
        'has_suspicious_words': int(bool(re.search(
            r'login|verify|secure|account|update|confirm|bank|paypal|signin',
            url, re.IGNORECASE
        ))),
    }])

What does this code do?

  • extract_url_features(url) takes a single URL string and returns a one-row DataFrame with the exact same 10 columns the model was trained on.
  • Each feature uses plain Python string operations (len(), .count(), re.search()) instead of pandas vectorized ops, because we are processing one URL at a time.
  • The function returns a DataFrame because scikit-learn's model.predict() expects tabular input with named columns.

You will not see a visible change from this function alone. The next chunk calls it and prints results.

Build the interactive scanning loop

Now you need the part that actually talks to the user. The loop prompts for a URL, feeds it through your feature extractor, runs the model's prediction, and prints a verdict.

  • Directly below the extract_url_features function, add the interactive scanning loop:
print("\n" + "=" * 50)
print("LIVE PHISHING URL SCANNER")
print("=" * 50)
print("Enter a URL to scan (or 'quit' to exit):\n")

while True:
    url = input("Scan URL > ").strip()
    if url.lower() == 'quit':
        print("Scanner closed. Stay safe online!")
        break
    if not url:
        continue
    if not url.startswith('http'):
        url = 'http://' + url

    features = extract_url_features(url)
    prediction = model.predict(features)[0]
    probabilities = model.predict_proba(features)[0]

    if prediction == 0:
        confidence = probabilities[0] * 100
        print(f"  [DANGER] PHISHING DETECTED - Confidence: {confidence:.1f}%")
    else:
        confidence = probabilities[1] * 100
        print(f"  [SAFE] Legitimate URL - Confidence: {confidence:.1f}%")
    print()

What does this code do?

  • The while True loop keeps prompting until the user types quit.
  • If the URL is missing a protocol (http:// or https://), the code prepends http:// so the feature extractor can parse the domain correctly.
  • model.predict() returns 0 (phishing) or 1 (legitimate). model.predict_proba() returns the probability for each class, which becomes the confidence percentage.
  • Save phishing_detector.py.

Before you run the script, think about what will happen when you paste a URL like http://192.168.1.1/login/verify-account.html. Based on the features your model learned to look for, do you think it will flag this as phishing or safe?

  • Run your scanner by executing this command in the terminal:
python phishing_detector.py
  • Wait for the training output to finish. You will see the familiar dataset stats, accuracy score, and feature importance list scroll by.
  • When you see the Scan URL > prompt, paste this suspicious URL:
http://192.168.1.1/login/verify-account.html

You should see [DANGER] PHISHING DETECTED with a confidence percentage. That URL triggers multiple phishing indicators: it uses an IP address instead of a domain name, contains suspicious keywords like "login" and "verify", and has a deep path structure.

  • Now test a legitimate URL. At the Scan URL > prompt, type:
google.com

You should see [SAFE] Legitimate URL with a high confidence percentage. The short, clean domain triggers none of the phishing signals.

  • Type quit to exit the scanner.

Scanner not giving results?

  • If you see a KeyError or column mismatch, make sure the feature names in extract_url_features match exactly with the column names used in features_df during training.
  • If the script hangs without showing the Scan URL > prompt, the model is still training. Wait 10-20 seconds for the training output to finish printing.
  • If you see an IndentationError, check that the function body and while loop body are indented with 4 spaces.

Help me debug my phishing URL scanner

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before moving on.

ⓧ I'd like to double check the full code

Your file is longer than 30 lines, so scroll through it and confirm these sections are present in order:

  • Imports (pandas, sklearn, re).
  • LOAD AND EXPLORE THE DATASET section with sample URL printing.
  • EXTRACT FEATURES AND TRAIN THE MODEL section with features_df, train/test split, and RandomForestClassifier training.
  • DETAILED PERFORMANCE ANALYSIS section with classification report and feature importance.
  • LIVE URL SCANNER section with the extract_url_features function.
  • The while True scanning loop that prompts Scan URL > and prints the verdict.

You just built a working AI-powered security tool from scratch. It loads data, trains a model, and gives instant verdicts on any URL you feed it. In the Secret Mission, you will upgrade it with risk levels and human-readable explanations that show exactly which features triggered the alert.

Secret mission

Add Risk Levels and Explain the Verdict

Your scanner gives a binary SAFE or DANGER verdict, but security analysts need more. Can you upgrade it to show risk levels (HIGH, MEDIUM, LOW) with color-coded output, and explain exactly which URL features triggered the alert?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally, so there are no ongoing costs or cloud resources to worry about. Decide whether to keep your files for future experimentation or delete them to reclaim disk space.

Resources you used:

  • The phishing-detector folder on your Desktop (contains phishing_detector.py and PhiUSIIL_Phishing_URL_Dataset.csv, approximately 70 MB total).
  • Python packages installed via pip (scikit-learn and pandas).
  • Python 3.13 installed on your system.
  • VS Code installed on your system.

Keep everything running

No action needed. Choose this if you want to keep experimenting with the phishing detector or modify it further.

  • Your detector runs locally at zero cost. There are no subscriptions, no cloud resources, and no recurring charges.
  • You can run python phishing_detector.py any time to scan URLs again.
  • Python and VS Code will remain installed for future projects.

Pause - I'll come back to this later

There is nothing to pause for this project. Everything runs locally on demand with no background processes or services.

  • No servers, containers, or cloud resources are running in the background.
  • The project only uses disk space (approximately 70 MB). It costs nothing to leave it sitting on your Desktop.
  • When you are ready to come back, open VS Code, open the phishing-detector folder, and run python phishing_detector.py again.

Delete - I don't want to use this again

Remove all project files and packages to start fresh and reclaim disk space.

  • Delete the project folder. On Windows, open a terminal and run:
cd ~\Desktop
rmdir /s /q phishing-detector

On macOS or Linux, run:

cd ~/Desktop
rm -rf phishing-detector
  • Uninstall the Python packages you installed for this project by running:
pip uninstall scikit-learn pandas -y
  • To uninstall Python or VS Code, open Settings on your computer, then go to Apps, then Installed apps. Search for Python 3.13 or Visual Studio Code and click Uninstall.
  • Only uninstall Python and VS Code if you are sure you will not use them for other projects.

Nice Work!

Nice Work!

You just built an AI-powered phishing URL detector from scratch. You went from a raw dataset of 235,000+ URLs to a live command-line scanner that gives instant security verdicts on any link you throw at it.

You've learned how to:

  • Engineered security-relevant features from raw URL strings, converting human-readable patterns (IP addresses, suspicious keywords, unusual length) into numbers a machine learning model can learn from.
  • Trained a Random Forest classifier on real cybersecurity research data, achieving 85%+ accuracy at distinguishing phishing URLs from legitimate ones.
  • Analyzed model performance using precision, recall, and feature importance, understanding why raw accuracy can hide dangerous blind spots in security applications.
  • Secret Mission: Added risk-level tiers (HIGH/MEDIUM/LOW) and human-readable explanations showing exactly which features triggered the alert.

Ready to quiz yourself?