{"id":47187073,"url":"https://github.com/WebDecoy/FCaptcha","last_synced_at":"2026-03-27T14:00:41.244Z","repository":{"id":331396566,"uuid":"1124476057","full_name":"WebDecoy/FCaptcha","owner":"WebDecoy","description":"Detect bots, vision AI agents, and headless browsers through 40+ behavioral signals and SHA-256 proof of work. Self-hosted, privacy-first, and fully open source.","archived":false,"fork":false,"pushed_at":"2026-03-02T02:21:14.000Z","size":1320,"stargazers_count":65,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-02T06:17:10.584Z","etag":null,"topics":["anti-bot","behavioral-analysis","bot-detection","captcha","fingerprinting","go","headless-browser-detection","nodejs","open-source","playwright-detection","privacy","proof-of-work","puppeteer-detection","python","scraping","scraping-protection","security","selenium-detector","self-hosted","web-security"],"latest_commit_sha":null,"homepage":"https://webdecoy.com/product/fcaptcha/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebDecoy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-29T04:54:40.000Z","updated_at":"2026-03-02T05:50:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/WebDecoy/FCaptcha","commit_stats":null,"previous_names":["webdecoy/fcaptcha"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/WebDecoy/FCaptcha","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebDecoy%2FFCaptcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebDecoy%2FFCaptcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebDecoy%2FFCaptcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebDecoy%2FFCaptcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebDecoy","download_url":"https://codeload.github.com/WebDecoy/FCaptcha/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebDecoy%2FFCaptcha/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31046738,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T09:35:52.079Z","status":"ssl_error","status_checked_at":"2026-03-27T09:35:20.916Z","response_time":164,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-bot","behavioral-analysis","bot-detection","captcha","fingerprinting","go","headless-browser-detection","nodejs","open-source","playwright-detection","privacy","proof-of-work","puppeteer-detection","python","scraping","scraping-protection","security","selenium-detector","self-hosted","web-security"],"created_at":"2026-03-13T10:00:23.984Z","updated_at":"2026-03-27T14:00:41.234Z","avatar_url":"https://github.com/WebDecoy.png","language":"JavaScript","funding_links":[],"categories":["Tools","Honeypots","Security Hardening"],"sub_categories":["Preventing"],"readme":"# F***Captcha\n\n**Open source CAPTCHA that blocks bots, vision AI agents, and automation - with a single click or less.**\n\n![License](https://img.shields.io/badge/license-MIT-blue.svg)\n![Go](https://img.shields.io/badge/Go-1.21+-00ADD8?logo=go)\n![Python](https://img.shields.io/badge/Python-3.12+-3776AB?logo=python)\n![Node](https://img.shields.io/badge/Node-20+-339933?logo=node.js)\n![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?logo=docker)\n\n**[Try the Live Demo](https://webdecoy.com/product/fcaptcha-demo/)**\n\n[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/WebDecoy/FCaptcha)\n[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template?referralCode=webdecoy\u0026template=https://github.com/WebDecoy/FCaptcha)\n\nFCaptcha is a modern CAPTCHA system designed to detect everything: traditional bots, headless browsers, automation frameworks, CAPTCHA farms, and the new generation of vision-based AI agents.\n\n## Features\n\n- **Single click or invisible** - Checkbox mode like Turnstile/reCAPTCHA v2, or invisible mode like reCAPTCHA v3\n- **Vision AI detection** - Specifically tuned to detect screenshot→API→click automation patterns\n- **Proof of Work** - Server-verified SHA-256 challenges that force compute cost on attackers\n- **Comprehensive bot detection** - Headless browsers, WebDriver, Puppeteer, Playwright, Selenium\n- **Behavioral analysis** - 40+ signals including micro-tremor, velocity variance, trajectory analysis\n- **Credential stuffing protection** - Form interaction analysis, timing detection, programmatic submit detection\n- **Self-hosted** - No external dependencies, run on your own infrastructure\n- **Privacy-first** - No persistent fingerprinting, no cross-site tracking\n- **Open algorithm** - Transparent scoring, fully auditable\n- **Multi-language servers** - Go, Python, or Node.js - pick your stack\n\n## Quick Start\n\n### Docker (recommended)\n\nOne command to deploy:\n\n```bash\ndocker run -d -p 3000:3000 -e FCAPTCHA_SECRET=my-secret ghcr.io/webdecoy/fcaptcha\n```\n\nThis gives you:\n- API at `http://localhost:3000/api/*`\n- Client JS at `http://localhost:3000/fcaptcha.js`\n- Demo page at `http://localhost:3000/demo/`\n\nWith Redis (for distributed state):\n\n```bash\nFCAPTCHA_SECRET=my-secret docker compose -f docker/docker-compose.yml up -d\n```\n\nDeploy to Fly.io:\n\n```bash\nfly launch --copy-config\nfly secrets set FCAPTCHA_SECRET=my-secret\n```\n\nBuild from source:\n\n```bash\ndocker build -f docker/Dockerfile -t fcaptcha .\ndocker run -d -p 3000:3000 -e FCAPTCHA_SECRET=my-secret fcaptcha\n```\n\n### Run from Source\n\nPick your language:\n\n**Go (fastest)**\n```bash\ncd server-go\ngo build -o fcaptcha-server\nFCAPTCHA_SECRET=your-secret ./fcaptcha-server\n```\n\n**Python (FastAPI)**\n```bash\ncd server-python\npip install -r requirements.txt\nFCAPTCHA_SECRET=your-secret python server.py\n```\n\n**Node.js (Express)**\n```bash\ncd server-node\nnpm install\nFCAPTCHA_SECRET=your-secret node server.js\n```\n\n### 2. Add to Your Site\n\n**Checkbox Mode (Interactive)**\n\n```html\n\u003cscript src=\"https://your-server.com/fcaptcha.js\"\u003e\u003c/script\u003e\n\u003cdiv id=\"captcha\"\u003e\u003c/div\u003e\n\n\u003cscript\u003e\n  FCaptcha.configure({ serverUrl: 'https://your-server.com' });\n\n  FCaptcha.render('captcha', {\n    siteKey: 'your-site-key',\n    callback: (token) =\u003e {\n      document.getElementById('token').value = token;\n    }\n  });\n\u003c/script\u003e\n```\n\n**Invisible Mode (Zero-Click)**\n\n```html\n\u003cscript src=\"https://your-server.com/fcaptcha.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n  FCaptcha.configure({ serverUrl: 'https://your-server.com' });\n\n  // Auto-protect all forms\n  FCaptcha.invisible({\n    siteKey: 'your-site-key',\n    autoScore: true\n  });\n\n  // Or manually score specific actions\n  const result = await FCaptcha.execute('your-site-key', {\n    action: 'login'\n  });\n\n  if (result.score \u003c 0.5) {\n    // Likely human\n  }\n\u003c/script\u003e\n```\n\n### 3. Verify on Your Backend\n\n```go\n// Go\nresp, _ := http.Post(\"https://your-server.com/api/token/verify\",\n    \"application/json\",\n    strings.NewReader(`{\"token\": \"...\", \"secret\": \"your-secret\"}`))\n\nvar result map[string]interface{}\njson.NewDecoder(resp.Body).Decode(\u0026result)\n\nif result[\"valid\"].(bool) \u0026\u0026 result[\"score\"].(float64) \u003c 0.5 {\n    // Valid request from human\n}\n```\n\n```python\n# Python\nimport requests\n\nresult = requests.post('https://your-server.com/api/token/verify',\n    json={'token': '...', 'secret': 'your-secret'}\n).json()\n\nif result['valid'] and result['score'] \u003c 0.5:\n    # Valid request from human\n```\n\n```javascript\n// Node.js\nconst result = await fetch('https://your-server.com/api/token/verify', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ token: '...', secret: 'your-secret' })\n}).then(r =\u003e r.json());\n\nif (result.valid \u0026\u0026 result.score \u003c 0.5) {\n  // Valid request from human\n}\n```\n\n## How It Works\n\nFCaptcha collects signals across multiple categories:\n\n### Proof of Work (Invisible Layer)\nBefore any verification, clients must solve a SHA-256 hashcash challenge:\n- **Challenge fetched on page load** - solving happens in background via Web Worker\n- **Non-blocking** - users never see it, computation happens while they fill forms\n- **Server-verified** - one-time use, replay protected, signed challenges\n- **Difficulty scaling** - datacenter IPs and high-rate requesters get harder puzzles\n- **Forces compute cost** - each attempt requires ~100-500ms of CPU time\n\nThis makes credential stuffing expensive: even if a bot passes all other checks, it still burns compute for every attempt.\n\n### Behavioral Signals (40% weight)\n- Mouse trajectory, velocity, acceleration curves\n- Micro-tremor detection (humans have natural hand shake at 3-25Hz)\n- Click precision and approach patterns\n- Pre-click exploration behavior\n- Overshoot corrections\n- Straight-line ratio detection\n\n### Environmental Signals (35% weight)\n- WebDriver/automation framework detection (Selenium, Puppeteer, Playwright, PhantomJS, Nightmare, Watir)\n- Headless browser indicators\n- Canvas/WebGL/Audio fingerprinting\n- Plugin and browser feature checks\n- User-Agent pattern matching\n\n### Temporal Signals (15% weight)\n- Proof of Work timing (reveals API round-trip latency)\n- Interaction timing patterns\n- Event sequence analysis\n- Page load to interaction timing\n\n### Form Interaction Signals (10% weight)\n- Programmatic form.submit() detection\n- Time from page load to submission\n- Events before submit (no events = bot)\n- Textarea keyboard analysis (paste detection, typing speed, rhythm)\n\n## Vision AI Detection\n\nModern AI agents work like this:\n1. Take screenshot\n2. Send to vision API (GPT-4V, Claude, etc.)\n3. Get click coordinates\n4. Execute click\n\nThis pattern has exploitable characteristics:\n\n| Signal | Human | Vision AI |\n|--------|-------|-----------|\n| Mouse movement | Natural curves, micro-tremor | Smooth/linear paths |\n| Pre-click behavior | Exploration, hesitation | Direct path to target |\n| Click timing | Variable, 200-800ms | Consistent, often faster |\n| Coordinate precision | Slight variance | Pixel-perfect |\n| PoW timing | Consistent with local execution | Delayed by API round-trip |\n\n## API Reference\n\n### GET /api/pow/challenge\nGet a Proof of Work challenge. Called automatically by the client on page load.\n\n```json\n// Request: GET /api/pow/challenge?siteKey=your-site-key\n\n// Response\n{\n  \"challengeId\": \"abc123...\",\n  \"prefix\": \"abc123:1703356800000:4\",\n  \"difficulty\": 4,\n  \"expiresAt\": 1703357100000,\n  \"sig\": \"def456...\"\n}\n```\n\nDifficulty scales based on:\n- Datacenter IPs: +1 difficulty\n- High request rate: +1 difficulty (max 6)\n\n### POST /api/verify\nVerify a checkbox CAPTCHA submission.\n\n```json\n// Request\n{\n  \"siteKey\": \"your-site-key\",\n  \"signals\": { /* collected signals */ },\n  \"powSolution\": {\n    \"challengeId\": \"abc123...\",\n    \"nonce\": 68455,\n    \"hash\": \"0000abc...\"\n  }\n}\n\n// Response\n{\n  \"success\": true,\n  \"score\": 0.15,\n  \"token\": \"...\",\n  \"recommendation\": \"allow\"\n}\n```\n\n### POST /api/score\nGet a score for invisible mode.\n\n```json\n// Request\n{\n  \"siteKey\": \"your-site-key\",\n  \"signals\": { /* collected signals */ },\n  \"action\": \"login\",\n  \"powSolution\": {\n    \"challengeId\": \"abc123...\",\n    \"nonce\": 68455,\n    \"hash\": \"0000abc...\"\n  }\n}\n\n// Response\n{\n  \"success\": true,\n  \"score\": 0.12,\n  \"token\": \"...\",\n  \"action\": \"login\"\n}\n```\n\n### POST /api/token/verify\nVerify a previously issued token (server-side).\n\n```json\n// Request\n{\n  \"token\": \"...\",\n  \"secret\": \"your-secret\"\n}\n\n// Response\n{\n  \"valid\": true,\n  \"site_key\": \"your-site-key\",\n  \"score\": 0.15,\n  \"timestamp\": 1703356800\n}\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `FCAPTCHA_SECRET` | Secret key for token signing | (required) |\n| `PORT` | Server port | 3000 |\n| `REDIS_URL` | Redis URL for distributed state | (in-memory) |\n\n### Score Thresholds\n\n| Score | Recommendation |\n|-------|----------------|\n| \u003c 0.3 | Allow - likely human |\n| 0.3 - 0.6 | Challenge - uncertain |\n| \u003e 0.6 | Block - likely bot |\n\n## Project Structure\n\n```\nfcaptcha/\n├── client/\n│   └── fcaptcha.js          # Client-side widget, signal collection, PoW Web Worker\n├── server-go/\n│   ├── main.go              # Go HTTP server + static file serving\n│   ├── scoring.go           # Scoring engine + PoW verification\n│   ├── detection.go         # IP reputation, header analysis, browser checks\n│   └── go.mod\n├── server-python/\n│   ├── server.py            # Python/FastAPI server + PoW\n│   ├── detection.py         # Detection modules\n│   └── requirements.txt\n├── server-node/\n│   ├── server.js            # Node.js/Express server + PoW\n│   ├── detection.js         # Detection modules\n│   └── package.json\n├── test/\n│   └── test-detection.js    # Comprehensive test suite (50 tests)\n├── demo/\n│   └── index.html           # Interactive demo page\n├── docker/\n│   ├── Dockerfile           # Multi-stage build (Go binary + client + demo)\n│   └── docker-compose.yml   # Docker compose with Redis\n├── .github/workflows/\n│   └── docker-publish.yml   # GHCR publish on release\n├── .dockerignore\n├── ARCHITECTURE.md          # Technical architecture documentation\n└── README.md\n```\n\n## Development\n\n```bash\n# Run Go server\ncd server-go \u0026\u0026 go run .\n\n# Run Python server\ncd server-python \u0026\u0026 python server.py\n\n# Run Node server\ncd server-node \u0026\u0026 node server.js\n\n# Open demo\nopen demo/index.html\n```\n\n### Running Tests\n\n```bash\n# Start a server first (any language)\ncd server-node \u0026\u0026 node server.js \u0026\n\n# Run the test suite\nnode test/test-detection.js\n\n# Expected output: 50 tests, all passing\n```\n\nThe test suite covers:\n- Bot user-agent detection (10 tests)\n- Headless browser detection (3 tests)\n- Datacenter IP detection (9 tests)\n- HTTP header analysis (3 tests)\n- Browser consistency checks (4 tests)\n- Behavioral signal analysis (2 tests)\n- Vision AI detection (3 tests)\n- Form interaction analysis (6 tests)\n- Proof of Work (6 tests)\n- Token verification (2 tests)\n- Invisible mode scoring (2 tests)\n\n## Contributing\n\nContributions welcome! Please read the architecture docs first.\n\nAreas that could use help:\n- Machine learning-based scoring\n- Integration libraries (React, Vue, etc.)\n- Admin dashboard\n- External IP intelligence API integration (IPQualityScore, etc.)\n- WebAssembly-based PoW for better mobile performance\n- Redis-backed distributed state (currently in-memory)\n\n## License\n\nMIT License - use freely, contribute back if you can.\n\n---\n\n**Privacy Note**: FCaptcha is designed with privacy in mind. No persistent fingerprinting, no cross-site tracking, no PII collection. All fingerprints are session-scoped and used only for bot detection.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWebDecoy%2FFCaptcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FWebDecoy%2FFCaptcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWebDecoy%2FFCaptcha/lists"}