const express = require('express'); const puppeteer = require("puppeteer-extra"); const pluginStealth = require("puppeteer-extra-plugin-stealth"); const { hcaptcha, hcaptchaToken } = require("puppeteer-hcaptcha"); // Gunakan puppeteer stealth puppeteer.use(pluginStealth()); const app = express(); app.use(express.json()); // Endpoint health check app.get('/', (req, res) => { res.json({ status: 'ok', message: 'hCaptcha Solver API is running', endpoints: { 'POST /solve': 'Solve hCaptcha with browser (Body: { url: string })', 'POST /solve-token': 'Get hCaptcha token only (Body: { url: string })', 'GET /solve-demo': 'Solve demo hCaptcha' } }); }); // Endpoint untuk solve hCaptcha dengan browser page app.post('/solve', async (req, res) => { const { url } = req.body; if (!url) { return res.status(400).json({ error: 'Missing required parameter: url' }); } let browser; const startTime = Date.now(); try { browser = await puppeteer.launch({ ignoreHTTPSErrors: true, headless: true, args: [ '--window-size=1920,1080', '--disable-dev-shm-usage', '--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security', '--disable-features=site-per-process', '--disable-blink-features=AutomationControlled', '--disable-gpu' ], }); const [page] = await browser.pages(); await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 }); await page.setDefaultNavigationTimeout(0); // Solve hCaptcha await hcaptcha(page); // Get token dari page const token = await page.evaluate(() => { const textarea = document.querySelector('[name="h-captcha-response"]'); return textarea ? textarea.value : null; }); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); await browser.close(); res.json({ success: true, token: token, duration: `${duration} seconds`, message: 'hCaptcha solved successfully' }); } catch (error) { if (browser) { await browser.close(); } console.error('Error solving captcha:', error); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.status(500).json({ success: false, error: error.message, duration: `${duration} seconds` }); } }); // Endpoint untuk get token only (lebih cepat) app.post('/solve-token', async (req, res) => { const { url } = req.body; if (!url) { return res.status(400).json({ error: 'Missing required parameter: url' }); } const startTime = Date.now(); try { // Metode ini lebih cepat karena langsung return token const token = await hcaptchaToken(url); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.json({ success: true, token: token, duration: `${duration} seconds`, message: 'hCaptcha token retrieved successfully' }); } catch (error) { console.error('Error getting token:', error); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.status(500).json({ success: false, error: error.message, duration: `${duration} seconds` }); } }); // Endpoint demo app.get('/solve-demo', async (req, res) => { const startTime = Date.now(); const demoUrl = "https://accounts.hcaptcha.com/demo?sitekey=4c672d35-0701-42b2-88c3-78380b0db560"; try { const token = await hcaptchaToken(demoUrl); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.json({ success: true, token: token, duration: `${duration} seconds`, message: 'Demo hCaptcha solved successfully' }); } catch (error) { console.error('Error solving demo captcha:', error); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.status(500).json({ success: false, error: error.message, duration: `${duration} seconds` }); } }); // Endpoint untuk solve dengan custom options app.post('/solve-advanced', async (req, res) => { const { url, waitForNavigation = false, timeout = 60000 } = req.body; if (!url) { return res.status(400).json({ error: 'Missing required parameter: url' }); } let browser; const startTime = Date.now(); try { browser = await puppeteer.launch({ ignoreHTTPSErrors: true, headless: true, args: [ '--window-size=1920,1080', '--disable-dev-shm-usage', '--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security', '--disable-features=site-per-process', '--disable-blink-features=AutomationControlled' ], }); const [page] = await browser.pages(); await page.goto(url, { waitUntil: 'networkidle2', timeout: timeout }); await page.setDefaultNavigationTimeout(0); // Solve hCaptcha await hcaptcha(page); // Tunggu jika diminta if (waitForNavigation) { await page.waitForTimeout(2000); } // Get token const token = await page.evaluate(() => { const textarea = document.querySelector('[name="h-captcha-response"]'); return textarea ? textarea.value : null; }); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); await browser.close(); res.json({ success: true, token: token, duration: `${duration} seconds`, message: 'hCaptcha solved successfully' }); } catch (error) { if (browser) { await browser.close(); } console.error('Error solving captcha:', error); const endTime = Date.now(); const duration = ((endTime - startTime) / 1000).toFixed(2); res.status(500).json({ success: false, error: error.message, duration: `${duration} seconds` }); } }); const PORT = process.env.PORT || 7860; app.listen(PORT, '0.0.0.0', () => { console.log(`🚀 Server running on port ${PORT}`); console.log(`📡 API ready at http://0.0.0.0:${PORT}`); });