Actor picture

Anti Captcha

petr_cermak/anti-captcha

No credit card required

Author's avatarPetr Cermak
  • Modified
  • Users13
  • Runs252

Dockerfile

# Dockerfile contains instructions how to build a Docker image that
# will contain all the code and configuration needed to run your actor.
# For a full Dockerfile reference,
# see https://docs.docker.com/engine/reference/builder/

# First, specify the base Docker image. Apify provides the following
# base images for your convenience:
#  apify/actor-node-basic (Node.js on Alpine Linux, small and fast)
#  apify/actor-node-chrome (Node.js + Chrome on Debian)
#  apify/actor-node-chrome-xvfb (Node.js + Chrome + Xvfb on Debian)
# For more information, see https://docs.apify.com/actor/build#base-images
# Note that you can use any other image from Docker Hub.
FROM apify/actor-node-basic

# Second, copy just package.json since it should be the only file
# that affects "npm install" in the next step, to speed up the build
COPY package.json ./

# Install NPM packages, skip optional and development dependencies to
# keep the image small. Avoid logging too much and print the dependency
# tree for debugging
RUN npm --quiet set progress=false \
 && npm install --only=prod --no-optional \
 && echo "Installed NPM packages:" \
 && npm list || true \
 && echo "Node.js version:" \
 && node --version \
 && echo "NPM version:" \
 && npm --version

# Next, copy the remaining files and directories with the source code.
# Since we do this after NPM install, quick build will be really fast
# for most source file changes.
COPY . ./

# Optionally, specify how to launch the source code of your actor.
# By default, Apify's base Docker images define the CMD instruction
# that runs the Node.js source code using the command specified
# in the "scripts.start" section of the package.json file.
# In short, the instruction looks something like this:
#
# CMD npm start

README.md

# My beautiful actor

Contains a documentation what your actor does and how to use it,
which is then displayed in the app or library. It's always a good
idea to write a good README.md, in a few months not even you
will remember all the details about the actor.

You can use [Markdown](https://guides.github.com/features/mastering-markdown/)
language for rich formatting.

main.js

const Apify = require('apify');
const fetch = require('node-fetch');

const postJson = async (url, body) => {
    const opt = {
        method: 'POST',
        body: JSON.stringify(body),
        headers: {'Content-Type': 'application/json'}
    };
    const response = await fetch(url, opt);
    return await response.json();
};

class AntiCaptchaTask {
    
    constructor(input){
        this.input = input;
        this.taskId = null;
        this.clientKey = input.clientKey;
    }
    
    async create(){
        const data = await postJson('http://api.anti-captcha.com/createTask', this.input);
        if(data.errorId > 0){throw new Error(data.errorDescription);}
        this.taskId = data.taskId;
        return data.taskId;
    }
    
    async getResult(){
        const body = {
            taskId: this.taskId,
            clientKey: this.clientKey,
        };
        const data = await postJson('http://api.anti-captcha.com/getTaskResult', body);
        if(data.errorId > 0){throw new Error(data.errorDescription);}
        return data;
    }

    async waitForResult(timeout = 600000){
        return new Promise((resolve, reject) => {
            const startedAt = new Date();
            const waitLoop = () => {
                if((new Date() - startedAt) > timeout){
                    reject(new Error("Waiting for result timed out."));
                }
                this.getResult().then((response) => {
                    if(response.errorId !== 0){
                        reject(new Error(response.errorDescription));
                    } 
                    else{
                        console.log(response);
                        if(response.status === 'ready'){resolve(response);}
                        else{
                            console.log('...');
                            setTimeout(waitLoop, 1000);
                        }
                    }
                }).catch((e) => reject(e));
            };
            waitLoop();
        });
    }
    
}

Apify.main(async () => {
    
    const input = await Apify.getValue('INPUT');
    if(!input.clientKey){
        throw new Error('ERROR: missing "clientKey" attribute in INPUT');
    }
    if(!input.task){
        throw new Error('ERROR: missing "task" attribute in INPUT');
    }
    if(!input.task.type){
        throw new Error('ERROR: missing "task.type" attribute in INPUT');
    }
    
    console.log('Solving captcha, type: ' + input.task.type);

    const task = new AntiCaptchaTask(input);
    console.log('Creating AntiCaptcha task...');
    await task.create();
    console.log('Waiting for result...');
    const result = await task.waitForResult();
    console.log('Captcha solving succesful.');
    await Apify.setValue('OUTPUT', result.solution);
    console.log('Solution: ');
    console.dir(result.solution);
});

package.json

{
    "name": "anti-captcha",
    "version": "0.0.1",
    "dependencies": {
        "apify": "^1.0.0",
        "node-fetch": "^2.6.1"
    },
    "scripts": {
        "start": "node main.js"
    },
    "author": "Petr Cermak"
}