| import express from 'express'; |
| import { chromium } from 'playwright-core'; |
| import cors from 'cors'; |
| import { solve } from './solver.js'; |
|
|
| const app = express(); |
| const PORT = process.env.PORT || 7860; |
|
|
| app.use(cors()); |
| app.use(express.json()); |
|
|
| app.get('/', (req, res) => { |
| res.json({ |
| status: 'ok', |
| message: 'reCAPTCHA Solver API is running', |
| endpoints: { |
| solve: '/api/solve?url=YOUR_URL', |
| health: '/health' |
| } |
| }); |
| }); |
|
|
| app.get('/health', (req, res) => { |
| res.json({ status: 'healthy' }); |
| }); |
|
|
| app.get('/api/solve', async (req, res) => { |
| const { url } = req.query; |
|
|
| if (!url) { |
| return res.status(400).json({ |
| error: 'Missing required parameter', |
| message: 'Please provide a URL parameter' |
| }); |
| } |
|
|
| let browser; |
| const startTime = Date.now(); |
|
|
| try { |
| console.log(`[API] Starting to solve reCAPTCHA for: ${url}`); |
|
|
| browser = await chromium.launch({ |
| headless: true, |
| args: [ |
| '--no-sandbox', |
| '--disable-setuid-sandbox', |
| '--disable-dev-shm-usage', |
| '--disable-gpu', |
| '--disable-software-rasterizer', |
| '--disable-extensions', |
| '--disable-blink-features=AutomationControlled' |
| ], |
| executablePath: process.env.PLAYWRIGHT_BROWSERS_PATH || '/usr/bin/chromium' |
| }); |
|
|
| const context = await browser.newContext({ |
| userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', |
| viewport: { width: 1280, height: 720 } |
| }); |
| |
| const page = await context.newPage(); |
| |
| await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }); |
|
|
| console.log('[API] Attempting to solve reCAPTCHA...'); |
| |
| await solve(page); |
|
|
| const solveTime = ((Date.now() - startTime) / 1000).toFixed(2); |
| console.log(`[API] reCAPTCHA solved in ${solveTime}s`); |
|
|
| const pageUrl = page.url(); |
| const pageTitle = await page.title(); |
|
|
| const token = await page.evaluate(() => { |
| const textarea = document.querySelector('[name="g-recaptcha-response"]'); |
| return textarea ? textarea.value : null; |
| }); |
|
|
| await browser.close(); |
|
|
| res.json({ |
| success: true, |
| message: 'reCAPTCHA solved successfully', |
| solveTime: `${solveTime}s`, |
| url: pageUrl, |
| title: pageTitle, |
| hasToken: !!token, |
| tokenLength: token ? token.length : 0, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| } catch (error) { |
| console.error('[API] Error solving reCAPTCHA:', error); |
|
|
| if (browser) { |
| await browser.close().catch(err => console.error('Error closing browser:', err)); |
| } |
|
|
| res.status(500).json({ |
| success: false, |
| error: 'Failed to solve reCAPTCHA', |
| message: error.message, |
| timestamp: new Date().toISOString() |
| }); |
| } |
| }); |
|
|
| app.post('/api/solve', async (req, res) => { |
| const { url, submitSelector } = req.body; |
|
|
| if (!url) { |
| return res.status(400).json({ |
| error: 'Missing required field', |
| message: 'Please provide a URL in the request body' |
| }); |
| } |
|
|
| let browser; |
| const startTime = Date.now(); |
|
|
| try { |
| console.log(`[API] Starting to solve reCAPTCHA for: ${url}`); |
|
|
| browser = await chromium.launch({ |
| headless: true, |
| args: [ |
| '--no-sandbox', |
| '--disable-setuid-sandbox', |
| '--disable-dev-shm-usage', |
| '--disable-gpu', |
| '--disable-blink-features=AutomationControlled' |
| ], |
| executablePath: process.env.PLAYWRIGHT_BROWSERS_PATH || '/usr/bin/chromium' |
| }); |
|
|
| const context = await browser.newContext({ |
| userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', |
| viewport: { width: 1280, height: 720 } |
| }); |
| |
| const page = await context.newPage(); |
| await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }); |
|
|
| console.log('[API] Attempting to solve reCAPTCHA...'); |
| await solve(page); |
|
|
| await page.waitForTimeout(2000); |
|
|
| if (submitSelector) { |
| await page.click(submitSelector); |
| await page.waitForTimeout(3000); |
| } |
|
|
| const solveTime = ((Date.now() - startTime) / 1000).toFixed(2); |
| console.log(`[API] reCAPTCHA solved in ${solveTime}s`); |
|
|
| const pageUrl = page.url(); |
|
|
| await browser.close(); |
|
|
| res.json({ |
| success: true, |
| message: 'reCAPTCHA solved successfully', |
| solveTime: `${solveTime}s`, |
| url: pageUrl, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| } catch (error) { |
| console.error('[API] Error solving reCAPTCHA:', error); |
|
|
| if (browser) { |
| await browser.close().catch(err => console.error('Error closing browser:', err)); |
| } |
|
|
| res.status(500).json({ |
| success: false, |
| error: 'Failed to solve reCAPTCHA', |
| message: error.message, |
| timestamp: new Date().toISOString() |
| }); |
| } |
| }); |
|
|
| app.listen(PORT, '0.0.0.0', () => { |
| console.log(`π reCAPTCHA Solver API running on port ${PORT}`); |
| console.log(`π Health check: http://localhost:${PORT}/health`); |
| console.log(`π§ Solve endpoint: http://localhost:${PORT}/api/solve?url=YOUR_URL`); |
| }); |
|
|
| process.on('SIGTERM', () => { |
| console.log('SIGTERM received, shutting down gracefully...'); |
| process.exit(0); |
| }); |
|
|
| process.on('SIGINT', () => { |
| console.log('SIGINT received, shutting down gracefully...'); |
| process.exit(0); |
| }); |