# Project export: HackTCHA

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2025
- Tagline: Obfuscation algorithms stress-test and strengthen CAPTCHAs against leading AI models
- Devpost: https://devpost.com/software/hacktcha
- GitHub: https://github.com/dubiels/treehacks2025
- Demo: https://treehacks2025-one.vercel.app/
- Video: https://www.youtube.com/embed/02syurYJ-z8?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — Karolina Dubiel (41 commits), Alayna Nguyen (29 commits), elizabethqiu (2 commits), luna-chen (1 commits)

## Devpost submission (written by the team)

### Inspiration

💡 Imagine you’re looking for a new pair of headphones. You read through reviews that claim the sound quality is amazing, only to discover later that these reviews were automated—created by bots trained to mimic human language, opinions, and emotions. This problem is only growing. In recent years, AI has become eerily good at solving CAPTCHAs—the very thing designed to separate humans from bots. Traditional CAPTCHA testing is outdated. Companies rarely know which CAPTCHAs remain effective against evolving AI threats, nor do they have a real-time leaderboard showing which CAPTCHA types are safest. Instead of waiting for hackers to exploit vulnerabilities, we’re building a live testbed where AI itself uncovers weaknesses—so we can design the next generation of human-friendly, bot-resistant security.

### What it does

🧑‍💻 HackTCHA tests how different AI models—like GPT, Google Gemini, Mistral, and Groq—perform against various CAPTCHA types (including text and multi-select image CAPTCHAs). Here’s how it works: 1. User Inputs The user pastes the image URL of a CAPTCHA. The user enters the correct response for that CAPTCHA (e.g., the text in the image, or which squares contain a car). 2. AI Testing Clicking “Test CAPTCHA” launches the AI models to solve the CAPTCHA. Each AI’s response is displayed alongside its accuracy (whether it got it right) and time to respond. 3. Obfuscation Tools If you want to make the CAPTCHA harder, you can add obfuscations: --> Random Noise – Distorts the image with Gaussian noise via Python. --> Stylization + Warp – Uses OpenCV to give the image an artistic look, then applies a non-linear warp. --> Diff-CAPTCHA – A novel approach combining denoising diffusion models, UNet, and style transfer for robust anti-bot CAPTCHAs. https://blowai.com/diffusion-based-captcha-system https://arxiv.org/abs/2308.08367 Each obfuscated result is assigned to a permalink via the Imgur API (this permalink is stored in a SQLite3 database) and displayed in the lefthand History tab. 4. Version History & Database A sidebar logs each obfuscation step with its own thumbnail. If you want to revert to a previous version, just click that thumbnail. All tests (images + AI responses) are saved in a SQLite3 database for easy reference and analytics.

### How we built it

🌲 🔹 Frontend React (JSX) – Main UI framework. Tailwind CSS (via CDN) – Styling the frontend. Lucide-react – Icons (Loader, Check, X, AlertTriangle, etc.). fetch API – Calls Flask backend for CAPTCHA solving & image processing. 🔹 Backend Flask (Python) – Web server handling CAPTCHA processing, obfuscation, and database operations. Flask-CORS – Enables cross-origin requests from frontend to backend. SQLite – Stores CAPTCHA image URLs. UUID – Generates unique filenames for obfuscated images. Pillow (PIL) – Handles image processing. OpenCV (cv2) – Applies obfuscation techniques (noise, blur, warping). NumPy – Performs numerical operations on image arrays. Requests – Fetches CAPTCHA images and uploads to Imgur. Base64 – Converts images for AI processing. 🔹 Image Hosting Imgur API – Uploads and retrieves obfuscated images. 🔹 AI CAPTCHA Solvers OpenAI (GPT-4o) Google Gemini (gemini-1.5-flash, gemini-2.0-flash) Mistral (pixtral-12b-2409) --> For multi-select captchas, the following are also available: Groq (llama-3.2-90b-vision-preview, llama-3.2-11b-vision-preview)

### Challenges we ran into

🔎 Imgur: Blocks request so we had to force convert it to png and append it Rate Limiting: When sending requests to the AI models in our project, we reached rate limits quickly which made it difficult to test our changes Obfuscation Complexity: Striking a balance between human readibility and AI confusion was difficult as some of our methods warped images either too much so that even humans had trouble reading it or too little such that AI models were still able to correctly guess the captcha Groq: Internal server issues as well as error messages that came from our use of imgur urls in our queries

### Accomplishments we're proud of

🎯 Wireframing on Figma to design an intuitive UI Learning documentation from different AI models to combine them all in the project Utilzing state of the art obfuscation model which we learned about from reviewing recent research papers about CAPTCHA Iterative development Deployed to Vercel and learned a lot of new technologies

### What we learned

👀 Learned about collaboration and CI/CD Different obfuscation techniques work better on different types of images and CAPTCHAs and AI models can be unreliable AI can beat certain CAPTCHAs more efficiently than we expected, prompting us to keep innovating. How to use Gemini, Groq, and Mistral as we were all beginners

### What's next

✅ More CAPTCHA Types: Expand beyond text and image selection to audio CAPTCHAs, puzzle CAPTCHAs, and 3D CAPTCHAs. Enterprise Integration: Offer an API so organizations can plug their own CAPTCHAs into our stress-tester and run daily or weekly scans to keep up with AI evolutions. Accessibility Testing: Explore ways to measure the impact of each obfuscation on visually impaired or dyslexic users, ensuring CAPTCHAs remain inclusive. Citations (papers we read) https://www.usenix.org/system/files/sec21fall-gao.pdf https://www.researchgate.net/publication/304995447_A_Survey_of_Current_Research_on_CAPTCHA https://www.irjms.com/wp-content/uploads/2024/07/Manuscript_IRJMS_0828_WS.pdf https://arxiv.org/abs/2308.08367 How HackTCHA Aligns with Sponsor Goals 💛 Education Grand Prize: HackTCHA aims to provide education about and raise awareness for AI security and adversarial techniques through a hands-on, interactive platform. By integrating easily into virtual classroom demos or work trainings, we’re educating the public about CAPTCHA vulnerabilities and obfuscation. Sustainability Prize: Best prototyping process We rapidly iterated on our CAPTCHA obfuscation methods—using minimal data and energy—to validate each approach before full-scale deployment. This lean, feedback-driven prototyping process highlights reduced resource consumption and responsible experimentation. Tesla: Excellence Prize: HackTCHA pushes AI excellence with new obfuscation algorithms that test and improve CAPTCHAs against top AI models. Our approach is creative, precise, and efficient, setting new standards in AI security and interpretability, aligning with Tesla’s focus on efficiency and precision. Google Cloud: Best Use of Gemini HackTCHA leverages the Gemini family of multimodal models to simultaneously handle text-based and image-based CAPTCHAs for robust stress-testing. By tapping into Gemini’s real-time streaming and advanced context capabilities, we can deliver rapid, accurate AI responses to secure websites. Vercel: Most Creative Use of Vercel in Edge AI track We deployed HackTCHA’s front end on Vercel for lightning-fast global access, integrating edge functions to handle quick CAPTCHA image transformations. This setup ensures minimal latency for AI queries, offering a seamless user experience with a creative spin on web-based AI tasks. Otsuka Valuenex: VALUENEX Big Data Visualization Award HackTCHA analyzes and visualizes CAPTCHA attack data to reveal AI success patterns and obfuscation effectiveness. Our easy-to-use dashboard makes complex metrics clear, aligning with VALUENEX’s focus on broad data insights. Codegen: Best Developer Tool HackTCHA’s obfuscation techniques and AI testing routines can be seamlessly integrated into developers’ workflows to bolster product security before shipping. Through easy-to-use endpoints and auto-generated scripts, it empowers dev teams to identify CAPTCHAs’ weak points with minimal friction. DAIN Labs: AI Agent Excellence & Innovation Awards HackTCHA orchestrates multiple autonomous AI agents that each employ different solving strategies to enable users to see what performs better Our dynamic agent collaboration, memory storage for past attempts, and adaptive obfuscation illustrate advanced workflow orchestration and responsible AI deployment. Delve: Best Agentic Workflow HackTCHA’s multi-agent system allows browser-based AI solvers to retrieve CAPTCHA images, analyze them, and respond, all within a streamlined, user-friendly interface. Each agent’s workflow is transparent and modular, exemplifying seamless online interaction and practical task execution. Delve: Most Secure App HackTCHA fortifies application security by rigorously testing and iterating on CAPTCHAs until they’re resistant to cutting-edge AI models. This iterative approach helps developers close security gaps, ensuring end-users remain protected from bot-driven threats. Delve: Most Intuitive UX Despite its complex underpinnings, HackTCHA’s interface is clean and straightforward—users can upload a CAPTCHA, run tests, and apply obfuscations in just a few clicks. Interactive visual feedback and version history tracking make advanced security testing feel approachable and streamlined. Groq: Best on Groq Multimodal App Challenge HackTCHA taps into Groq’s capabilities to handle text and image inputs simultaneously, stress-testing CAPTCHAs with cutting-edge compute. By leveraging Groq for rapid inference across multiple modalities, we demonstrate innovative, high-performance AI that tackles real-world security challenges. Mistral: Best Use of Mistral AI API HackTCHA integrates Mistral’s advanced language and vision models to evaluate CAPTCHA difficulty and accuracy in tandem. By coupling Mistral with our obfuscation techniques, we can surface the fine-grained strengths or weaknesses of each CAPTCHA design. Neo: Most Likely to Become a Business HackTCHA solves a pressing problem—bot infiltration—at scale, offering a B2B SaaS model to continuously assess and update CAPTCHA robustness. Its wide market potential, from e-commerce to Web3, positions it for significant growth and real-world adoption. OpenAI: Most Creative Use of OpenAI API HackTCHA introduces a creative approach: we use the OpenAI API to generate adversarial obfuscations and orchestrate multi-turn agentic CAPTCHA-solving approaches. By mixing GPT’s image reasoning and language processing, we push the boundaries of creative security testing. Paradigm: Best Spreadsheet-Adjacent Hack HackTCHA stores AI accuracy, response times, and obfuscation details in a live spreadsheet. This direct integration with spreadsheet data not only tracks improvements but also empowers teams to iterate swiftly on CAPTCHA design. Rox: Best Agents Hack HackTCHA automates CAPTCHA-solving with multi-agent LLM orchestration, employing context fetching, prompt orchestration, and tool calling. Each agent refines its approach based on prior failures, showcasing advanced agentic workflows and complex technical design. Vespa.ai: Best Hack Using a Vision Language Model HackTCHA uses VLMs for both text-based and image-based CAPTCHA interpretation, measuring their strengths and weaknesses side-by-side. This approach not only tests vision-language understanding but also exposes how adversarial obfuscations can challenge even top-tier VLMs. Warp: Best Developer Tool HackTCHA provides a robust, developer-centric toolkita for testing and refining CAPTCHA security right within their workflows. With minimal setup, devs can quickly evaluate AI models, apply obfuscations, and iterate, enhancing productivity and bolstering application defense.

## README (from the GitHub repository)

# HackTCHA 🧑‍💻

Test your CAPTCHAs against multiple industry-standard AI models to assess their resistance to automated solving.

## Setup Instructions

### Mac/Linux (Terminal)

```
python3 -m venv captcha_env
source captcha_env/bin/activate
```

### 2️⃣ Install Dependencies

```
pip install -r requirements.txt
```

### Prerequisites

-   Node.js and npm
-   Git (optional)

### Installation

1. **Clone the repository** (or download and extract the ZIP):

```bash
git clone [your-repo-url]
cd [project-directory]
```

2. **Set up the React frontend**:

```bash
# Install Node dependencies
npm init -y
npm install react react-dom lucide-react
npm install --save-dev vite @vitejs/plugin-react
```

3. **Create the project structure**:

```
project_root/
├── package.json
├── vite.config.js
└── frontend/
    ├── index.html
    ├── components/
    │   └── CaptchaTester.jsx
    └── main.jsx
```

4. **Configure Vite**:
   Create `vite.config.js` in the project root:

```javascript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
    plugins: [react()],
    root: "frontend",
    build: {
        outDir: "../dist",
    },
    resolve: {
        extensions: [".js", ".jsx"],
    },
});
```

5. **Update package.json**:
   Make sure your package.json includes these scripts:

```json
{
    "scripts": {
        "dev": "vite",
        "build": "vite build",
        "preview": "vite preview"
    }
}
```

### Running the Application

In one terminal, start server.py:

```bash
python server.py
```

Leave that running, in another terminal, run:

```bash
npm run dev
```

This will run on http://localhost:5173


## Detected evidence (automated analysis)

Indexed codebase: 11 recognized source files, 61 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Flask (technology) — claimed on Devpost, not found in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code
- Tailwind CSS (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (15 of 15)

```
agents/agent.py
captcha_images.db
captcha.db
demo-links.md
frontend/components/CaptchaTester.jsx
frontend/index.html
frontend/main.jsx
frontend/styles.css
init_db.py
package.json
README.md
requirements.txt
server.py
temp.py
vite.config.js
```

### Dependencies

- package.json: @babel/core@^7.26.9, @babel/preset-react@^7.26.3, @vitejs/plugin-react@^4.3.4, lucide-react@^0.475.0, react@^19.0.0, react-dom@^19.0.0, vite@^6.1.0

### Recent commits (newest first)

- SO PROUD OF US!! NICE JOB!!
- updated readme
- palaubits
- Updated correct links
- enabled openai
- added a footer and bottom padding
- Merge branch 'main' of github.com:dubiels/treehacks2025
- Default image
- merge captcha
- Better UI
- Fixed background issue
- just kidding it doesn't work
- working clear button (kinda ugly tho)
- lowkey messed up version
- Uncommented openai stuff, left TODOs for recommenting it back
- Fixed background white corner issue
- prettier history function kinda?
- removed temp files
- fully functional (but ugly) history function!!!!
- working mvp of history

## Key source files (fetched from GitHub, selected and truncated for size)

### demo-links.md

```markdown
### Text Captcha

Easy
Td4eva
https://www.okta.com/sites/default/files/media/image/2021-04/Okta-Captcha.png

Medium
arch dsjbka
https://cf-assets.www.cloudflare.com/slt3lc6tev37/4wCmCWsWiTB8ZG64tBVEKY/0499192ff9baf249fa2b45843c5d2948/recaptcha.png

<!-- Harder
6T9JBCDS
https://cf-assets.www.cloudflare.com/slt3lc6tev37/3pwMuJ55jpErAafgrWbyTr/e6c487ac6e4288dfe284db72b88ea3d1/captcha.png -->

Hardest
palaubits
https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/CAPTCHA_test.png/460px-CAPTCHA_test.png

### Multiselect Captcha

Hard (Taxi 3x3)
1,4,5
https://miro.medium.com/v2/resize:fit:1092/1*jcXPqzruCRYHItBKcVolrw.jpeg

Hardest (Bus 4x4)
3,4,7,8,11,12,15,16
https://global.discourse-cdn.com/brave/optimized/3X/4/2/42fdad275b488712ceed1f095789fa0453cab2f7_2_330x500.jpeg

```

### package.json

```
{
  "name": "treehacks2025",
  "version": "1.0.0",
  "description": "Follow these steps to set up your environment and run the script.",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.26.9",
    "@babel/preset-react": "^7.26.3",
    "lucide-react": "^0.475.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.3.4",
    "vite": "^6.1.0"
  }
}

```

### requirements.txt

```
��a n n o t a t e d - t y p e s = = 0 . 7 . 0  
 a n y i o = = 4 . 8 . 0  
 c a c h e t o o l s = = 5 . 5 . 1  
 c e r t i f i = = 2 0 2 5 . 1 . 3 1  
 c h a r s e t - n o r m a l i z e r = = 3 . 4 . 1  
 c o l o r a m a = = 0 . 4 . 6  
 e v a l _ t y p e _ b a c k p o r t = = 0 . 2 . 2  
 f l a s k = = 3 . 0 . 2  
 f l a s k - c o r s = = 4 . 0 . 0  
 g o o g l e - a i - g e n e r a t i v e l a n g u a g e = = 0 . 6 . 1 5  
 g o o g l e - a p i - c o r e = = 2 . 2 4 . 1  
 g o o g l e - a p i - p y t h o n - c l i e n t = = 2 . 1 6 1 . 0  
 g o o g l e - a u t h = = 2 . 3 8 . 0  
 g o o g l e - a u t h - h t t p l i b 2 = = 0 . 2 . 0  
 g o o g l e - g e n e r a t i v e a i = = 0 . 8 . 4  
 g o o g l e a p i s - c o m m o n - p r o t o s = = 1 . 6 7 . 0  
 g r p c i o = = 1 . 7 0 . 0  
 g r p c i o - s t a t u s = = 1 . 7 0 . 0  
 h 1 1 = = 0 . 1 4 . 0  
 h t t p c o r e = = 1 . 0 . 7  
 h t t p l i b 2 = = 0 . 2 2 . 0  
 h t t p x = = 0 . 2 8 . 1  
 i d n a = = 3 . 1 0  
 j s o n p a t h - p y t h o n = = 1 . 0 . 6  
 m i s t r a l a i = = 1 . 5 . 0  
 m y p y - e x t e n s i o n s = = 1 . 0 . 0  
 n u m p y = = 1 . 2 6 . 4  
 o p e n c v - p y t h o n = = 4 . 9 . 0 . 8 0  
 p i l l o w = = 1 1 . 1 . 0  
 p r o t o - p l u s = = 1 . 2 6 . 0  
 p r o t o b u f = = 5 . 2 9 . 3  
 p y a s n 1 = = 0 . 6 . 1  
 p y a s n 1 _ m o d u l e s = = 0 . 4 . 1  
 p y d a n t i c = = 2 . 1 0 . 6  
 p y d a n t i c _ c o r e = = 2 . 2 7 . 2  
 p y p a r s i n g = = 3 . 2 . 1  
 p y t h o n - d a t e u t i l = = 2 . 9 . 0 . p o s t 0  
 p y t h o n - d o t e n v = = 1 . 0 . 1  
 r e q u e s t s = = 2 . 3 2 . 3  
 r s a = = 4 . 9  
 s i x = = 1 . 1 7 . 0  
 s n i f f i o = = 1 . 3 . 1  
 t q d m = = 4 . 6 7 . 1  
 t y p i n g - i n s p e c t = = 0 . 9 . 0  
 t y p i n g _ e x t e n s i o n s = = 4 . 1 2 . 2  
 u r i t e m p l a t e = = 4 . 1 . 1  
 u r l l i b 3 = = 2 . 3 . 0  
 a i o h t t p  
 
```

### frontend/main.jsx

```javascript
import React from 'react';
import { createRoot } from 'react-dom/client';
import CaptchaTester from './components/CaptchaTester';

const root = createRoot(document.getElementById('root'));
root.render(<CaptchaTester />);
```

### server.py

```python
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
import requests
import io
import base64
import os
import numpy as np
import cv2
from PIL import Image
from agents.agent import solve_captcha, check_text_correctness, check_multiselect_correctness
import uuid
import sqlite3
from PIL import Image


# Flask app setup
app = Flask(__name__, static_folder="dist", static_url_path="/")
CORS(app, resources={r"/*": {"origins": "*"}})

IMAGE_STORAGE_PATH = "public/temp"

# Imgur API credentials (replace with your actual client ID)
DATABASE = "captcha.db"  # SQLite database file
IMGUR_CLIENT_ID = os.getenv('IMGUR_CLIENT_ID')

# ------------------ DATABASE SETUP ------------------

@app.route("/get_images", methods=["GET"])
def get_images():
    """Retrieve all stored image URLs from the database, ordered by oldest first."""
    try:
        conn = sqlite3.connect(DATABASE)
        cursor = conn.cursor()
        
        cursor.execute("SELECT url FROM images ORDER BY id ASC")  # Fetch URLs in order
        rows = cursor.fetchall()
        conn.close()
        
        image_urls = [row[0] for row in rows]  # Extract URLs from rows
        
        return jsonify({"images": image_urls}), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def print_db_contents():
    """Reads all stored image URLs from the database and prints them."""
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()

    cursor.execute("SELECT * FROM images")  # Fetch all rows
    rows = cursor.fetchall()  # Retrieve data

    conn.close()  # Close connection

    if rows:
        print("\n🔹 **Stored Image URLs in Database** 🔹\n")
        for row in rows:
            print(f"ID: {row[0]}, URL: {row[1]}")
    else:
        print("\n⚠️ No images found in the database.\n")

def initialize_db():
    """Clears the database and recreates the images table on every server restart."""
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()

    # ✅ Drop the table if it exists (this wipes all stored data)
    cursor.execute("DROP TABLE IF EXISTS images")

    # ✅ Recreate the table
    cursor.execute("""
        CREATE TABLE images (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            url TEXT NOT NULL
        )
    """)

    conn.commit()
    conn.close()
    print("✅ Database wiped and reinitialized on server restart.")

initialize_db()  # Initialize DB when server starts

def save_image_url_to_db(image_url):
    """Stores the uploaded Imgur URL in SQLite."""
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()
    cursor.execute("INSERT INTO images (url) VALUES (?)", (image_url,))
    conn.commit()
    conn.close()

@app.route("/", defaults={'path': ''})
@app.route("/")
def serve(path):
    if path != "" and os.path.exists(app.static_folder + '/' + path):
        return send_from_directory(app.static_folder, path)
    return send_from_directory(app.static_folder, 'index.html')

# ------------------ IMAGE OBFUSCATION & UPLOAD ------------------
def upload_to_imgur(image_path):
    """Uploads an image to Imgur and returns the correct direct URL."""
    headers = {"Authorization": f"Client-ID {IMGUR_CLIENT_ID}"}

    # ✅ Detect the actual image format (PNG, JPEG, etc.)
    with Image.open(image_path) as img:
        img_format = img.format.lower()  # Convert to lowercase ('png', 'jpeg', etc.)

    # ✅ Upload the image to Imgur
    with open(image_path, "rb") as file:
        response = requests.post(
            "https://api.imgur.com/3/upload",
            headers=headers,
            files={"image": file},
        )

    data = response.json()
    if data.get("success"):
        imgur_id = data["data"]["id"]  # ✅ Get the Imgur image ID

        # ✅ Ensure the correct extension
        if img_format in ["jpeg", "jpg"]:
            return f"https://i.imgur.com/{imgur_id}.jpg"
        elif img_format == "png":
            return f"https://i.imgur.com/{imgur_id}.png"
        else:
            return f"https://i.imgur.com/{imgur_id}"  # Default (just in case)

    else:
        raise Exception(f"Imgur upload failed: {data}")

@app.route("/save_image_url", methods=["POST"])
def save_image_url():
    """Saves a new image URL to the database."""
    try:
        data = request.get_json()
        if "image_url" not in data:
            return jsonify({"error": "Image URL is required"}), 400

        image_url = data["image_url"]
        
        # ✅ Save to database
        save_image_url_to_db(image_url)
        
        print(f"✅ Image URL saved: {image_url}")  # Debugging
        
        return jsonify({"message": "Image URL saved successfully."}), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route("/obfuscate", methods=["POST"])
def obfuscate():
    """Apply obfuscation, upload to Imgur, and return the public link."""
    try:
        data = request.get_json()
        if "image_url" not in data:
            return jsonify({"error": "Image URL is required"}), 400

        image_url = data["image_url"]

        # ✅ Fetch the image the same way React does
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
        }
        response = requests.get(image_url, headers=headers, stream=True)

        if response.status_code != 200:
            return jsonify({"error": f"Failed to fetch image, status code: {response.status_code}"}), 400

        print("✅ Image fetched successfully from:", image_url)  # Debugging

        # ✅ Convert the image to an array
        image = Image.open(io.BytesIO(response.content)).convert("RGB")
        img_np = np.array(image)

        # Apply obfuscation
        obfuscated_img = apply_obfuscation(img_np)
        obfuscated_pil = Image.fromarray(obfuscated_img)

        # Save temporarily
        filename = f"{uuid.uuid4().hex}.png"
        temp_dir = "public/temp"


[truncated — 15039 more characters]
```

### vite.config.js

```javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  root: 'frontend',
  build: {
    outDir: '../dist'
  },
  resolve: {
    extensions: ['.js', '.jsx']
  }
})
```

### init_db.py

```python
import sqlite3

DATABASE = "captcha.db"

def initialize_db():
    """Creates the database and table for storing Imgur URLs."""
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()

    # Create table if it doesn't exist
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS images (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            url TEXT NOT NULL
        )
    """)

    conn.commit()
    conn.close()
    print("Database initialized successfully!")

if __name__ == "__main__":
    initialize_db()

```

### temp.py

```python
import asyncio
import concurrent.futures

@app.route("/solve", methods=["POST"])
def solve():
    """Handle CAPTCHA solving via an image URL asynchronously."""
    try:
        data = request.get_json()
        is_multiselect = data.get("is_multiselect", False)
        validation_function = check_multiselect_correctness if is_multiselect else check_text_correctness

        if "image_url" not in data or "correct_answer" not in data:
            return jsonify({"error": "Image URL and correct answer are required"}), 400

        image_url = data["image_url"]
        correct_answer = data["correct_answer"].strip().lower()

        print(f"🔹 Processing CAPTCHA: {image_url} (Multiselect: {is_multiselect})")

        # ✅ Use ThreadPoolExecutor to run models concurrently
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

        with concurrent.futures.ThreadPoolExecutor() as executor:
            futures = []

            # ✅ Process OpenAI GPT-4o (Direct URL)
            futures.append(loop.run_in_executor(executor, solve_captcha, image_url, "gpt-4o", is_multiselect))

            # ✅ Process Gemini and Mistral (Base64)
            response = requests.get(image_url)
            if response.status_code != 200:
                return jsonify({"error": "Failed to fetch image from URL"}), 400

            image = Image.open(io.BytesIO(response.content))
            buffered = io.BytesIO()
            image.save(buffered, format="PNG")
            base64_image = base64.b64encode(buffered.getvalue()).decode("utf-8")

            gemini_models = ["gemini-1.5-flash", "gemini-1.5-pro"]
            mistral_models = ["pixtral-12b-2409"]
            groq_models = ["llama-3.2-90b-vision-preview", "llama-3.2-11b-vision-preview"]

            for model in gemini_models + mistral_models:
                futures.append(loop.run_in_executor(executor, solve_captcha, base64_image, model, is_multiselect))

            for model in groq_models:
                futures.append(loop.run_in_executor(executor, solve_captcha, image_url, model, is_multiselect))

            # ✅ Collect results as they complete
            results = []
            completed_tasks = loop.run_until_complete(asyncio.gather(*futures))

            for (model_name, response_text, time_taken) in completed_tasks:
                response_text = response_text.strip().lower()
                results.append({
                    "agent": model_name,
                    "response": response_text,
                    "time": f"{time_taken}s",
                    "correct": validation_function(correct_answer, response_text),
                })

        return jsonify({
            "display_image": image_url,
            "correct_response": correct_answer,
            "results": results
        })

    except Exception as e:
        print(f"❌ Error in /solve: {e}")  # ✅ Debugging
        return jsonify({"error": str(e)}), 500

```

### frontend/index.html

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>HackTCHA</title>
        <script src="https://cdn.tailwindcss.com"></script>
        <link rel="stylesheet" href="styles.css" />
    </head>
    <body>
        <div id="root"></div>
        <script type="module" src="/main.jsx"></script>
    </body>
</html>

```

### frontend/styles.css

```css
/* Custom Scrollbar - FORCE APPLY */
::-webkit-scrollbar {
    width: 8px !important; /* Adjust width */
  }
  
  ::-webkit-scrollbar-track {
    background: #111827 !important; /* Dark background */
  }
  
  ::-webkit-scrollbar-thumb {
    background: #374151 !important; /* Darker scrollbar */
    border-radius: 10px !important;
  }
  
  ::-webkit-scrollbar-thumb:hover {
    background: #4b5563 !important; /* Lighter on hover */
  }
  
  /* For Firefox */
  * {
    scrollbar-width: thin !important;
    scrollbar-color: #374151 #111827 !important; /* Thumb color | Track color */
  }
  
```

[2 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]