MCPcopy
hub / github.com/gcui-art/suno-api / getCaptcha

Method getCaptcha

src/lib/SunoApi.ts:307–429  ·  view source on GitHub ↗

* Checks for CAPTCHA verification and solves the CAPTCHA if needed * @returns {string|null} hCaptcha token. If no verification is required, returns null

()

Source from the content-addressed store, hash-verified

305 * @returns {string|null} hCaptcha token. If no verification is required, returns null
306 */
307 public async getCaptcha(): Promise<string|null> {
308 if (!await this.captchaRequired())
309 return null;
310
311 logger.info('CAPTCHA required. Launching browser...')
312 const browser = await this.launchBrowser();
313 const page = await browser.newPage();
314 await page.goto('https://suno.com/create', { referer: 'https://www.google.com/', waitUntil: 'domcontentloaded', timeout: 0 });
315
316 logger.info('Waiting for Suno interface to load');
317 // await page.locator('.react-aria-GridList').waitFor({ timeout: 60000 });
318 await page.waitForResponse('**/api/project/**\\?**', { timeout: 60000 }); // wait for song list API call
319
320 if (this.ghostCursorEnabled)
321 this.cursor = await createCursor(page);
322
323 logger.info('Triggering the CAPTCHA');
324 try {
325 await page.getByLabel('Close').click({ timeout: 2000 }); // close all popups
326 // await this.click(page, { x: 318, y: 13 });
327 } catch(e) {}
328
329 const textarea = page.locator('.custom-textarea');
330 await this.click(textarea);
331 await textarea.pressSequentially('Lorem ipsum', { delay: 80 });
332
333 const button = page.locator('button[aria-label="Create"]').locator('div.flex');
334 this.click(button);
335
336 const controller = new AbortController();
337 new Promise<void>(async (resolve, reject) => {
338 const frame = page.frameLocator('iframe[title*="hCaptcha"]');
339 const challenge = frame.locator('.challenge-container');
340 try {
341 let wait = true;
342 while (true) {
343 if (wait)
344 await waitForRequests(page, controller.signal);
345 const drag = (await challenge.locator('.prompt-text').first().innerText()).toLowerCase().includes('drag');
346 let captcha: any;
347 for (let j = 0; j < 3; j++) { // try several times because sometimes 2Captcha could return an error
348 try {
349 logger.info('Sending the CAPTCHA to 2Captcha');
350 const payload: paramsCoordinates = {
351 body: (await challenge.screenshot({ timeout: 5000 })).toString('base64'),
352 lang: process.env.BROWSER_LOCALE
353 };
354 if (drag) {
355 // Say to the worker that he needs to click
356 payload.textinstructions = 'CLICK on the shapes at their edge or center as shown above—please be precise!';
357 payload.imginstructions = (await fs.readFile(path.join(process.cwd(), 'public', 'drag-instructions.jpg'))).toString('base64');
358 }
359 captcha = await this.solver.coordinates(payload);
360 break;
361 } catch(err: any) {
362 logger.info(err.message);
363 if (j != 2)
364 logger.info('Retrying...');

Callers 1

generateSongsMethod · 0.95

Calls 5

captchaRequiredMethod · 0.95
launchBrowserMethod · 0.95
clickMethod · 0.95
waitForRequestsFunction · 0.90
sleepFunction · 0.90

Tested by

no test coverage detected