Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,20 +317,19 @@ that the target page expects in `cf-turnstile-response`.
| `action` | no | Value of the widget's `data-action` attribute, if set. |
| `data` | no | Custom payload from the widget's `data-cdata` attribute, if set. |
| `pagedata` | no | Value of the `chlPageData` parameter, needed for some Cloudflare challenge pages beyond the basic widget. Note the lowercase, single-word spelling -- unlike every other field on this page, the real API does not accept `pageData`. |

There's no `userAgent` input for this type -- the worker picks its own while solving
and returns it in the response instead (see below).
| `userAgent` | no | User-Agent used by the browser that will submit the token. Required for Cloudflare Challenge pages. |

**Response:** `token` -- submit as `cf-turnstile-response` -- and `userAgent`, the User-Agent the
worker actually solved with. The token is tied to that fingerprint, so submit it with that exact
User-Agent, not one you chose yourself.
worker solved with. The token is tied to that fingerprint. For Cloudflare Challenge pages, pass
the browser's User-Agent in the task and use the same value when submitting the token.

```javascript
import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.TurnstileProxyless({
websiteURL: 'https://example.com/login',
websiteKey: 'YOUR_WEBSITE_KEY'
websiteKey: 'YOUR_WEBSITE_KEY',
userAgent: 'Mozilla/5.0 ...'
});
const result = await captchaSolver.solve(task);
console.log(result.token);
Expand Down
11 changes: 6 additions & 5 deletions src/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,22 @@ export interface TurnstileProxylessParams {
* the API does not accept `pageData`.
*/
pagedata?: string | null;
/** User-Agent used by the browser that will submit the token. */
userAgent?: string | null;
}

/** Parameters of {@link Turnstile}. */
export interface TurnstileParams extends TurnstileProxylessParams, ProxyParams {}

/**
* Cloudflare Turnstile without a proxy (`TurnstileTaskProxyless`).
* There is no `userAgent` input: the worker picks one and returns it in the solution.
* Solution: {@link TurnstileSolution}.
*
* @see https://captcha-solver.com/en/docs/captcha-types#cloudflare-turnstile
*/
export class TurnstileProxyless extends BaseTask<TurnstileSolution> {
constructor({ websiteURL, websiteKey, action = null, data = null, pagedata = null }: TurnstileProxylessParams) {
super({ type: 'TurnstileTaskProxyless', websiteURL, websiteKey, action, data, pagedata });
constructor({ websiteURL, websiteKey, action = null, data = null, pagedata = null, userAgent = null }: TurnstileProxylessParams) {
super({ type: 'TurnstileTaskProxyless', websiteURL, websiteKey, action, data, pagedata, userAgent });
}
}

Expand All @@ -365,8 +366,8 @@ export class TurnstileProxyless extends BaseTask<TurnstileSolution> {
* @see https://captcha-solver.com/en/docs/captcha-types#cloudflare-turnstile
*/
export class Turnstile extends BaseTask<TurnstileSolution> {
constructor({ websiteURL, websiteKey, action = null, data = null, pagedata = null, proxyType, proxyAddress, proxyPort, proxyLogin = null, proxyPassword = null }: TurnstileParams) {
super({ type: 'TurnstileTask', websiteURL, websiteKey, action, data, pagedata, proxyType, proxyAddress, proxyPort, proxyLogin, proxyPassword });
constructor({ websiteURL, websiteKey, action = null, data = null, pagedata = null, userAgent = null, proxyType, proxyAddress, proxyPort, proxyLogin = null, proxyPassword = null }: TurnstileParams) {
super({ type: 'TurnstileTask', websiteURL, websiteKey, action, data, pagedata, userAgent, proxyType, proxyAddress, proxyPort, proxyLogin, proxyPassword });
}
}

Expand Down
8 changes: 5 additions & 3 deletions tests/unit/sync/turnstile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ describe('TurnstileProxyless', () => {
expect(result.pageData).toBeUndefined();
});

test('does not accept userAgent as input -- the API only returns it in the solution', () => {
test('includes the browser userAgent for Cloudflare Challenge pages', () => {
const task = new Tasks.TurnstileProxyless({
websiteURL: 'https://example.com',
websiteKey: 'test_key',
userAgent: 'Mozilla/5.0'
});

const result = task.toDict();
expect(result.userAgent).toBeUndefined();
expect(result.userAgent).toBe('Mozilla/5.0');
});
});

Expand All @@ -55,13 +55,15 @@ describe('Turnstile with proxy', () => {
websiteKey: 'test_key',
proxyType: 'http',
proxyAddress: '1.2.3.4',
proxyPort: 8080
proxyPort: 8080,
userAgent: 'Mozilla/5.0'
});

const result = task.toDict();
expect(result.type).toBe('TurnstileTask');
expect(result.proxyType).toBe('http');
expect(result.proxyAddress).toBe('1.2.3.4');
expect(result.userAgent).toBe('Mozilla/5.0');
});
});

Expand Down
Loading