The usual cause is that the reCAPTCHA plugin was never registered. In the commonly reported Apify example, an addPlugins() function contains puppeteer.use(RecaptchaPlugin(...)), but the function is never called. Without that registration, page.solveRecaptchas() is not added to the page, so JavaScript raises TypeError: page.solveRecaptchas is not a function.
Register puppeteer-extra-plugin-recaptcha before launching the browser or crawler, pass that same puppeteer-extra instance to the crawler, and make sure the page was created after the plugin hooks were installed. If you deliberately reuse an existing about:blank page, invoke the plugin’s onPageCreated hook for that page.
What the TypeError actually tells you
solveRecaptchas() is supplied by puppeteer-extra-plugin-recaptcha; it is not part of an unmodified Puppeteer Page. The error only proves that the property is not callable on the particular page object at the moment you call it. It does not prove that a CAPTCHA is present, that your provider token is invalid, or that the solving service is unavailable.
Those provider and detection questions come later. First, make the method exist on the page.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
Fix the registration omission first
Register the plugin before launching
The plugin is attached with puppeteer.use(plugin). Keep the plugin object in a variable when you may need its lifecycle hook later:
const puppeteer = require('puppeteer-extra');
const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha');
const recaptcha = RecaptchaPlugin({
provider: {
id: '2captcha',
token: process.env.TWOCAPTCHA_API_KEY
}
});
puppeteer.use(recaptcha);
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const result = await page.solveRecaptchas();
console.dir(result, { depth: null });
} finally {
await browser.close();
}
})();
Install the packages in the project that runs this file, export TWOCAPTCHA_API_KEY, and run it with Node.js. The important ordering is: create the plugin, call puppeteer.use(...), then launch and create pages.
Call the setup function
If your project wraps registration in a helper, invoke it on every startup path before the crawler obtains a browser:
function addPlugins() {
puppeteer.use(RecaptchaPlugin({
provider: {
id: '2captcha',
token: process.env.TWOCAPTCHA_API_KEY
}
}));
}
addPlugins();
// Only now create the crawler or call puppeteer.launch().
Defining addPlugins() is not enough. A function body does nothing until execution reaches addPlugins().
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsRank #2
Make sure the crawler uses the same instance
A second frequent cause is registering the plugin on one object and giving the crawler another. For example, registering on a locally imported puppeteer-extra while the crawler launches with regular puppeteer leaves its pages unmodified.
- Import
puppeteer-extraonce in the process. - Call
.use(RecaptchaPlugin(...))on that object. - Pass that exact object as the crawler’s launcher using the launcher option supported by your installed Apify/Crawlee version.
- Do not create a second Puppeteer import in a helper and assume registration is shared.
The Apify report that prompted this error dates from October 17, 2021. It demonstrates the omitted setup call in that sample, but it does not establish how every current PuppeteerCrawler release creates pages. Check the versions installed in your own project and the actual launcher path.
Check whether the page missed the plugin lifecycle
The plugin documentation calls out a targeted edge case: reusing an already open about:blank tab instead of creating a page with browser.newPage(). That page may have existed before the plugin could attach its hooks, so solveRecaptchas is absent even though registration is correct.
Preferred approach: create a managed page
After registering the plugin, use await browser.newPage() (or your crawler’s normal page-creation flow), then navigate and call the method. This lets the plugin run its normal page-created lifecycle.
Rank #3
When an existing page must be reused
Keep the plugin instance and manually run its page-created hook before solving:
const pages = await browser.pages();
const page = pages[0];
// The plugin README documents this workaround for a reused about:blank page.
await recaptcha.onPageCreated(page);
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const result = await page.solveRecaptchas();
Use this only for pages intentionally reused from browser.pages(). If you control page creation, a fresh plugin-managed page is simpler and less error-prone.
Separate a missing method from a solving failure
Once registration and lifecycle hooks are correct, the call can still report a normal solving problem. The plugin expects a configured provider, such as the provider object shown above. A missing or exhausted provider account, an invalid token, or a provider-side failure is not the same defect as an undefined method.
The documented result object exposes captchas, filtered, solutions, solved, and error. The plugin’s default behavior reports errors in the returned error property rather than necessarily throwing. Calling solveRecaptchas() on a page with no CAPTCHA is allowed; the promise resolves normally.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #4
Interpret the result in order
- If JavaScript throws
page.solveRecaptchas is not a function, return to registration, instance identity, and page lifecycle checks. - If the method exists and the result contains an
error, inspect provider credentials, account status, and the provider response. - If
captchasis empty, there may simply be no supported CAPTCHA on the page. - Use
solutionsandsolvedto see what the plugin attempted and completed; usefilteredto understand detections excluded by its filters.
A practical diagnostic sequence
- Confirm the package imports. Ensure the process that runs the crawler can resolve both
puppeteer-extraandpuppeteer-extra-plugin-recaptcha, rather than a different dependency tree. - Prove registration executes. Put a log immediately before and after
puppeteer.use(recaptcha). If the second log never appears, the crawler cannot receive a configured instance. - Check object identity. Verify the launcher passed to the crawler is the same
puppeteerobject on which.use()ran. - Inspect the page origin. Confirm the page was created after registration. If it came from
browser.pages(), applyrecaptcha.onPageCreated(page)or replace it withbrowser.newPage(). - Check the method before calling it. A temporary assertion makes the failure location explicit:
if (typeof page.solveRecaptchas !== 'function') throw new Error('reCAPTCHA plugin is not attached to this page'); - Enable plugin diagnostics. Run with
DEBUG=puppeteer-extra,puppeteer-extra-plugin:*and inspect the registration and page-hook messages. - Only then investigate the provider. Check the configured provider ID, token, account funds, and returned result fields after the method is present.
Common symptoms, causes and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
page.solveRecaptchas is not a function immediately |
puppeteer.use() never ran, often because a setup helper was never called. |
Invoke the helper before crawler/browser startup and verify it logs. |
| Plugin appears configured, but the crawler’s page lacks the method | The crawler uses regular Puppeteer or a different puppeteer-extra instance. |
Pass the registered instance as the launcher and remove duplicate imports. |
| Only a reused tab fails | The existing about:blank page missed plugin hooks. |
Create a fresh page or call await recaptcha.onPageCreated(page). |
The method exists but result has error |
Provider configuration or provider-side solving failure. | Validate provider ID/token and inspect the returned result; this is no longer a registration error. |
| The method exists and no CAPTCHA is reported | No supported CAPTCHA was detected on that page. | Review the target URL and the captchas/filtered fields; no solver call may be necessary. |
Keep package and lifecycle assumptions explicit
Do not “fix” this TypeError by blindly upgrading every dependency. The documented report is from 2021, and Apify/Crawlee page-creation behavior can differ by package version. Record the installed versions, read the launcher option for that version, and reproduce with a minimal script using one registered puppeteer-extra instance. If the minimal script works but the crawler does not, the remaining difference is the crawler’s launcher or page lifecycle.
Also remember that a successful method lookup says nothing about whether a site permits automated access or whether a CAPTCHA provider will solve a particular challenge. Follow the target site’s terms and your provider’s requirements.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your actual task is obtaining a clean image or PDF of a webpage—not solving its CAPTCHA—ScreenshotNeo is the first option to try. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. It also offers an MCP server for AI agents with take_screenshot, get_page_info and capture_pdf.
One GET request is enough:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the full option set, including full-page and element captures, device and retina settings, PDF page ranges, custom CSS or JavaScript, clicks, waits, blocked resources, headers, cookies, geolocation, caching, signed links, asynchronous webhooks and bulk capture.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →The same request in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. If that matches your job, create a free ScreenshotNeo account.
Best Value
FAQ
Is solveRecaptchas() available on every Puppeteer page?
No. It is added by puppeteer-extra-plugin-recaptcha only after the plugin is registered and its page hooks run.
Does this error mean the CAPTCHA provider is down?
No. A provider outage or bad token can occur only after the method exists and a solve attempt returns an error.
Can I reuse an existing browser tab?
Yes, but the plugin documentation warns that a pre-existing about:blank tab may not be hooked. Prefer browser.newPage(), or call the plugin’s onPageCreated hook for the reused page.
Recommended Free Tools
Frequently Asked Questions
Is solveRecaptchas() available on every Puppeteer page?
No. It is added by puppeteer-extra-plugin-recaptcha only after the plugin is registered and its page hooks run.
Does this error mean the CAPTCHA provider is down?
No. Provider outages and invalid tokens are later-stage failures; this TypeError means the page object does not have the plugin method.
Can I reuse an existing browser tab?
Yes, but a pre-existing about:blank page may not be hooked. Prefer browser.newPage(), or invoke the plugin’s onPageCreated hook for that page.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

