Spaces:
Build error
Build error
| 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}`); | |
| }); |