Please complete the security check to access www.cloudflare.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Why do I have to complete a CAPTCHA?
+
+
Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.
+
+
+
+
What can I do to prevent this in the future?
+
+
+
If you are on a personal connection, like at home, you can run an anti-virus scan on your device to make sure it is not infected with malware.
+
+
If you are at an office or shared network, you can ask the network administrator to run a scan across the network looking for misconfigured or infected devices.
+
+
+
Another way to prevent getting this page in the future is to use Privacy Pass. You may need to download version 2.0 now from the Chrome Web Store.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/test-captcha.js b/test/test-captcha.js
index b537232..3421daa 100644
--- a/test/test-captcha.js
+++ b/test/test-captcha.js
@@ -64,111 +64,224 @@ describe('Cloudscraper', function () {
expect(promise).to.be.rejectedWith(errors.CaptchaError).and.notify(done);
});
});
-
- for (let stage = 0; stage < 4; stage++) {
- const desc = {
- 0: 'should resolve reCAPTCHA (version as on 10.04.2019) when user calls captcha.submit()',
- 1: 'should callback with an error if user calls captcha.submit(error)',
- 2: 'should resolve reCAPTCHA (version as on 10.04.2019) when the onCaptcha promise resolves',
- 3: 'should callback with an error if the onCaptcha promise is rejected'
- };
-
- // Run this test 4 times
- it(desc[stage], function (done) {
- const secret = '6b132d85d185a8255f2451d48fe6a8bee7154ea2-1555377580-1800-AQ1azEkeDOnQP5ByOpwUU/RdbKrmMwHYpkaenRvjPXtB0w8Vbjn/Ceg62tfpp/lT799kjDLEMMuDkEMqQ7iO51kniWCQm00BQvDGl+D0h/WvXDWO96YXOUD3qrqUTuzO7QbUOinc8y8kedvOQkr4c0o=';
- const siteKey = '6LfBixYUAAAAABhdHynFUIMA_sa4s-XsJvnjtgB0';
- const expectedError = new Error('anti-captcha failed!');
-
- helper.router
- .get('/test', function (req, res) {
- res.sendCaptcha('cf_recaptcha_15_04_2019.html');
- })
- .get('/cdn-cgi/l/chk_captcha', function (req, res) {
- res.send(requestedPage);
+ describe('reCAPTCHA (version as on 10.04.2019)', () => {
+ for (let stage = 0; stage < 4; stage++) {
+ const desc = {
+ 0: 'should resolve when user calls captcha.submit()',
+ 1: 'should callback with an error if user calls captcha.submit(error)',
+ 2: 'should resolve when the onCaptcha promise resolves',
+ 3: 'should callback with an error if the onCaptcha promise is rejected'
+ };
+
+ // Run this test 4 times
+ it(desc[stage], function (done) {
+ const secret = '6b132d85d185a8255f2451d48fe6a8bee7154ea2-1555377580-1800-AQ1azEkeDOnQP5ByOpwUU/RdbKrmMwHYpkaenRvjPXtB0w8Vbjn/Ceg62tfpp/lT799kjDLEMMuDkEMqQ7iO51kniWCQm00BQvDGl+D0h/WvXDWO96YXOUD3qrqUTuzO7QbUOinc8y8kedvOQkr4c0o=';
+ const siteKey = '6LfBixYUAAAAABhdHynFUIMA_sa4s-XsJvnjtgB0';
+ const expectedError = new Error('anti-captcha failed!');
+
+ helper.router
+ .get('/test', function (req, res) {
+ res.sendCaptcha('cf_recaptcha_15_04_2019.html');
+ })
+ .get('/cdn-cgi/l/chk_captcha', function (req, res) {
+ res.send(requestedPage);
+ });
+
+ const onCaptcha = sinon.spy(function (options, response, body) {
+ expect(options).to.be.an('object');
+ expect(response).to.be.instanceof(http.IncomingMessage);
+ expect(body).to.be.a('string');
+
+ sinon.assert.match(response, {
+ isCloudflare: true,
+ isHTML: true,
+ isCaptcha: true,
+ captcha: sinon.match.object
+ });
+
+ sinon.assert.match(response.captcha, {
+ url: uri, // <-- Deprecated
+ uri: sinon.match.same(response.request.uri),
+ form: { s: secret },
+ siteKey: siteKey,
+ submit: sinon.match.func
+ });
+
+ // Simulate what the user should do here
+ response.captcha.form['g-recaptcha-response'] = 'foobar';
+
+ switch (stage) {
+ case 0:
+ // User green lights form submission
+ response.captcha.submit();
+ break;
+ case 1:
+ // User reports an error when solving the reCAPTCHA
+ response.captcha.submit(expectedError);
+ break;
+ case 2:
+ // User green lights form submission by resolving the returned promise
+ return Promise.resolve();
+ case 3:
+ // User reports an error by rejecting the returned promise
+ return Promise.reject(expectedError);
+ }
});
-
- const onCaptcha = sinon.spy(function (options, response, body) {
- expect(options).to.be.an('object');
- expect(response).to.be.instanceof(http.IncomingMessage);
- expect(body).to.be.a('string');
-
- sinon.assert.match(response, {
- isCloudflare: true,
- isHTML: true,
- isCaptcha: true,
- captcha: sinon.match.object
+
+ const firstParams = helper.extendParams({ onCaptcha, uri });
+ const secondParams = helper.extendParams({
+ onCaptcha,
+ method: 'GET',
+ uri: helper.resolve('/cdn-cgi/l/chk_captcha'),
+ headers: {
+ Referer: uri
+ },
+ qs: {
+ s: secret,
+ 'g-recaptcha-response': 'foobar'
+ }
});
-
- sinon.assert.match(response.captcha, {
- url: uri, // <-- Deprecated
- uri: sinon.match.same(response.request.uri),
- form: { s: secret },
- siteKey: siteKey,
- submit: sinon.match.func
+
+ const options = { onCaptcha, uri };
+
+ const promise = cloudscraper.get(options, function (error, response, body) {
+ switch (stage) {
+ case 0:
+ case 2:
+ expect(error).to.be.null;
+
+ expect(onCaptcha).to.be.calledOnce;
+
+ expect(Request).to.be.calledTwice;
+ expect(Request.firstCall).to.be.calledWithExactly(firstParams);
+ expect(Request.secondCall).to.be.calledWithExactly(secondParams);
+
+ expect(body).to.be.equal(requestedPage);
+ expect(promise).to.eventually.equal(requestedPage).and.notify(done);
+ break;
+ case 1:
+ case 3:
+ expect(error).to.be.instanceOf(errors.CaptchaError);
+ expect(error.error).to.be.an('error');
+ expect(error).to.have.property('errorType', 1);
+ expect(error.message).to.include(expectedError.message);
+ expect(promise).to.be.rejectedWith(errors.CaptchaError).and.notify(done);
+ break;
+ }
});
-
- // Simulate what the user should do here
- response.captcha.form['g-recaptcha-response'] = 'foobar';
-
- switch (stage) {
- case 0:
- // User green lights form submission
- response.captcha.submit();
- break;
- case 1:
- // User reports an error when solving the reCAPTCHA
- response.captcha.submit(expectedError);
- break;
- case 2:
- // User green lights form submission by resolving the returned promise
- return Promise.resolve();
- case 3:
- // User reports an error by rejecting the returned promise
- return Promise.reject(expectedError);
- }
- });
-
- const firstParams = helper.extendParams({ onCaptcha, uri });
- const secondParams = helper.extendParams({
- onCaptcha,
- method: 'GET',
- uri: helper.resolve('/cdn-cgi/l/chk_captcha'),
- headers: {
- Referer: uri
- },
- qs: {
- s: secret,
- 'g-recaptcha-response': 'foobar'
- }
});
+ }
+ });
- const options = { onCaptcha, uri };
-
- const promise = cloudscraper.get(options, function (error, response, body) {
- switch (stage) {
- case 0:
- case 2:
- expect(error).to.be.null;
-
- expect(onCaptcha).to.be.calledOnce;
+ describe('reCAPTCHA (version as on 01.12.2019)', () => {
+ for (let stage = 0; stage < 4; stage++) {
+ const desc = {
+ 0: 'should resolve when user calls captcha.submit()',
+ 1: 'should callback with an error if user calls captcha.submit(error)',
+ 2: 'should resolve when the onCaptcha promise resolves',
+ 3: 'should callback with an error if the onCaptcha promise is rejected'
+ };
+
+ // Run this test 4 times
+ it(desc[stage], function (done) {
+ const secret = '0bd666f149acf02bbc05bba3b1bb';
+ const siteKey = '6LfBixYUAAAAABhdHynFUIMA_sa4s-XsJvnjtgB0';
+ const rayId = '53dfe8147d2a9e73';
+ const expectedError = new Error('anti-captcha failed!');
+
+ helper.router
+ .get('/test', function (req, res) {
+ res.sendCaptcha('cf_recaptcha_01_12_2019.html');
+ })
+ .post('/', function (req, res) {
+ res.send(requestedPage);
+ });
+
+ const onCaptcha = sinon.spy(function (options, response, body) {
+ expect(options).to.be.an('object');
+ expect(response).to.be.instanceof(http.IncomingMessage);
+ expect(body).to.be.a('string');
+
+ sinon.assert.match(response, {
+ isCloudflare: true,
+ isHTML: true,
+ isCaptcha: true,
+ captcha: sinon.match.object
+ });
+
+ sinon.assert.match(response.captcha, {
+ url: uri, // <-- Deprecated
+ uri: sinon.match.same(response.request.uri),
+ form: { r: secret, id: rayId },
+ siteKey: siteKey,
+ submit: sinon.match.func
+ });
+
+ // Simulate what the user should do here
+ response.captcha.form['g-recaptcha-response'] = 'foobar';
+
+ switch (stage) {
+ case 0:
+ // User green lights form submission
+ response.captcha.submit();
+ break;
+ case 1:
+ // User reports an error when solving the reCAPTCHA
+ response.captcha.submit(expectedError);
+ break;
+ case 2:
+ // User green lights form submission by resolving the returned promise
+ return Promise.resolve();
+ case 3:
+ // User reports an error by rejecting the returned promise
+ return Promise.reject(expectedError);
+ }
+ });
+
+ const firstParams = helper.extendParams({ onCaptcha, uri });
+ const secondParams = helper.extendParams({
+ onCaptcha,
+ method: 'POST',
+ uri: helper.resolve('/?__cf_chl_captcha_tk__=e8844bdff35ae5e'),
+ qs: { __cf_chl_captcha_tk__: 'e8844bdff35ae5e' },
+ headers: {
+ Referer: helper.resolve('/test')
+ },
+ form: {
+ r: secret,
+ id: rayId,
+ 'g-recaptcha-response': 'foobar'
+ }
+ });
- expect(Request).to.be.calledTwice;
- expect(Request.firstCall).to.be.calledWithExactly(firstParams);
- expect(Request.secondCall).to.be.calledWithExactly(secondParams);
+ const options = { onCaptcha, uri };
+
+ const promise = cloudscraper.get(options, function (error, response, body) {
+ switch (stage) {
+ case 0:
+ case 2:
+ expect(error).to.be.null;
+
+ expect(onCaptcha).to.be.calledOnce;
+
+ expect(Request).to.be.calledTwice;
+ expect(Request.firstCall).to.be.calledWithExactly(firstParams);
+ expect(Request.secondCall).to.be.calledWithExactly(secondParams);
- expect(body).to.be.equal(requestedPage);
- expect(promise).to.eventually.equal(requestedPage).and.notify(done);
- break;
- case 1:
- case 3:
- expect(error).to.be.instanceOf(errors.CaptchaError);
- expect(error.error).to.be.an('error');
- expect(error).to.have.property('errorType', 1);
- expect(error.message).to.include(expectedError.message);
- expect(promise).to.be.rejectedWith(errors.CaptchaError).and.notify(done);
- break;
- }
+ expect(body).to.be.equal(requestedPage);
+ expect(promise).to.eventually.equal(requestedPage).and.notify(done);
+ break;
+ case 1:
+ case 3:
+ expect(error).to.be.instanceOf(errors.CaptchaError);
+ expect(error.error).to.be.an('error');
+ expect(error).to.have.property('errorType', 1);
+ expect(error.message).to.include(expectedError.message);
+ expect(promise).to.be.rejectedWith(errors.CaptchaError).and.notify(done);
+ break;
+ }
+ });
});
- });
- }
+ };
+ });
});