How I got over 6,000 stars in under an hour

java

!! Note: This blog post is rather old and may be based on outdated information.

I recently saw a blog post on someone getting 5,000 stars in less than 24 hours, and I wanted to top it. I was able to get ~1k/10min.

changelog-nightly-image

To start off on this journey, I searched for a good way to create fake accounts in Java, since I know the language best. I stumbled across a library made for testing websites called HtmlUnit. Using this, it was easy to reverse engineer the website and get the fields I needed to create an account. Here’s how the code looked:

String n = getRandomUsername();
final HtmlPage page = client.getPage("https://github.com/join");
HtmlInput username = (HtmlInput) page.getElementById("user_login");
HtmlInput email = (HtmlInput) page.getElementById("user_email");
HtmlInput password = (HtmlInput) page.getElementById("user_password");
HtmlInput password_confirm = (HtmlInput) page.getElementById("user_password_confirmation");
HtmlButton signup = (HtmlButton) page.getElementById("signup_button");
username.setValueAttribute(n);
email.setValueAttribute(n + "@gmail.com");
password.setValueAttribute(n + "1");
password_confirm.setValueAttribute(n + "1");
signup.click();

final HtmlPage repoPage = client.getPage("https://github.com/" + repo);
HtmlButton star = (HtmlButton) repoPage.getByXPath("//button[@aria-label=\"Star this repository\"]").get(0);
star.click();

The first part goes to the join page and gets all the fields and fills them in. This works because GitHub doesn’t require email verification before you can do stuff. Next, I go to a repository and hit the star button. Using this there is also a bunch of other stuff we can do.

final HtmlPage phase = client.getPage("https://github.com/phase");
final HtmlButton follow = (HtmlButton) phase.getByXPath("//button[@aria-label=\"Follow this person\"]").get(0);
follow.click();

This will get the follow button and click it.

To generate random usernames, I made a quick character frequency algorithm.

static final Random rand = new Random();

public String getRandomUsername() {
    int desired_length = 6;

    StringBuffer buf = new StringBuffer(desired_length);

    for (int i = 0; i < desired_length; ++i) {
        buf.append(getRandomCharacter());
    }

    return buf.toString() + rand.nextInt(999);
}

public char getRandomCharacter() {
    float v = (float) Math.random();

    char c = frequencies[0].character;
    float f = frequencies[0].frequency;

    for (CharacterFrequency cf : frequencies) {
        if (v < cf.frequency && cf.frequency < f) {
            c = cf.character;
            f = cf.frequency;
        }
    }

    return c;
}

private class CharacterFrequency {
    public float frequency;
    public char character;

    public CharacterFrequency(char c, float f) {
        character = c;
        frequency = f;
    }
}

private CharacterFrequency[] frequencies;

{
    frequencies = new CharacterFrequency[] {
            new CharacterFrequency('a', 0.8f),
            new CharacterFrequency('b', 0.6f),
            new CharacterFrequency('c', 0.4f),
            new CharacterFrequency('d', 0.4f),
            new CharacterFrequency('e', 0.8f),
            new CharacterFrequency('f', 0.4f),
            new CharacterFrequency('g', 0.2f),
            new CharacterFrequency('h', 0.4f),
            new CharacterFrequency('i', 0.8f),
            new CharacterFrequency('j', 0.4f),
            new CharacterFrequency('k', 0.4f),
            new CharacterFrequency('l', 0.4f),
            new CharacterFrequency('m', 0.4f),
            new CharacterFrequency('n', 0.4f),
            new CharacterFrequency('o', 0.8f),
            new CharacterFrequency('p', 0.4f),
            new CharacterFrequency('q', 0.4f),
            new CharacterFrequency('r', 0.4f),
            new CharacterFrequency('s', 0.4f),
            new CharacterFrequency('t', 0.6f),
            new CharacterFrequency('u', 0.8f),
            new CharacterFrequency('v', 0.1f),
            new CharacterFrequency('w', 0.1f),
            new CharacterFrequency('x', 0.5f),
            new CharacterFrequency('y', 0.1f),
            new CharacterFrequency('z', 0.1f),
    };
}

Using HtmlUnit, you can essentially hack any website to your needs. Except Twitter, they require phone verification.

Here is the full file in all of its glory:

package xyz.jadonfowler.hackgithub;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;

import java.util.Random;

public class HackGitHub {

    /*
     * IDs: user_login : _-# user_email : ___@___ user_password : ______#
     * user_password_confirmation : ^ signup_button
     */
    public static void main(String... args) {
        for (int i = 0; i < 16; i++) {
            new Thread(new StarRunnable()).start();
        }
    }

    WebClient client;

    HackGitHub() {
        this.client = new WebClient();
    }

    public void follow(String who) {
        try {
            this.client = new WebClient();
            String n = getRandomUsername();
            System.out.print("Using username '" + n + "'...");

            final HtmlPage page = client.getPage("https://github.com/join");
            HtmlInput username = (HtmlInput) page.getElementById("user_login");
            HtmlInput email = (HtmlInput) page.getElementById("user_email");
            HtmlInput password = (HtmlInput) page
                    .getElementById("user_password");
            HtmlInput password_confirm = (HtmlInput) page
                    .getElementById("user_password_confirmation");
            HtmlButton signup = (HtmlButton) page
                    .getElementById("signup_button");
            username.setValueAttribute(n);
            email.setValueAttribute(n + "@gmail.com");
            password.setValueAttribute(n + "1");
            password_confirm.setValueAttribute(n + "1");
            signup.click();

            final HtmlPage phase = client.getPage("https://github.com/" + who);
            final HtmlButton follow = (HtmlButton) phase.getByXPath(
                    "//button[@aria-label=\"Follow this person\"]").get(0);
            follow.click();
            System.out.println("Done");
        } catch (Exception e) {
            System.out.println("FAIL");
        }
    }

    public void star(String repo) {
        try {
            this.client = new WebClient();
            String n = getRandomUsername();
            System.out.print("Using username '" + n + "'...");

            final HtmlPage page = client.getPage("https://github.com/join");
            HtmlInput username = (HtmlInput) page.getElementById("user_login");
            HtmlInput email = (HtmlInput) page.getElementById("user_email");
            HtmlInput password = (HtmlInput) page
                    .getElementById("user_password");
            HtmlInput password_confirm = (HtmlInput) page
                    .getElementById("user_password_confirmation");
            HtmlButton signup = (HtmlButton) page
                    .getElementById("signup_button");
            username.setValueAttribute(n);
            email.setValueAttribute(n + "@gmail.com");
            password.setValueAttribute(n + "1");
            password_confirm.setValueAttribute(n + "1");
            signup.click();

            final HtmlPage repoPage = client.getPage("https://github.com/" + repo);
//            final HtmlButton follow = (HtmlButton) phase.getByXPath(
//                    "//button[@aria-label=\"Follow this person\"]").get(0);
//            follow.click();
            HtmlButton star = (HtmlButton) repoPage.getByXPath("//button[@aria-label=\"Star this repository\"]").get(0);
            star.click();
            System.out.println("Done");
        } catch (Exception e) {
            System.out.println("FAIL");
        }
    }

    static Random rand = new Random();

    public String getRandomUsername() {
        int desired_length = 6;

        StringBuffer buf = new StringBuffer(desired_length);

        for (int i = 0; i < desired_length; ++i) {
            buf.append(getRandomCharacter());
        }

        return buf.toString() + rand.nextInt(999);
    }

    public char getRandomCharacter() {
        float v = (float) Math.random();

        char c = frequencies[0].character;
        float f = frequencies[0].frequency;

        for (CharacterFrequency cf : frequencies) {
            if (v < cf.frequency && cf.frequency < f) {
                c = cf.character;
                f = cf.frequency;
            }
        }

        return c;
    }

    private class CharacterFrequency {
        public float frequency;
        public char character;

        public CharacterFrequency(char c, float f) {
            character = c;
            frequency = f;
        }
    }

    private CharacterFrequency[] frequencies;

    {
        frequencies = new CharacterFrequency[] {
                new CharacterFrequency('a', 0.8f),
                new CharacterFrequency('b', 0.6f),
                new CharacterFrequency('c', 0.4f),
                new CharacterFrequency('d', 0.4f),
                new CharacterFrequency('e', 0.8f),
                new CharacterFrequency('f', 0.4f),
                new CharacterFrequency('g', 0.2f),
                new CharacterFrequency('h', 0.4f),
                new CharacterFrequency('i', 0.8f),
                new CharacterFrequency('j', 0.4f),
                new CharacterFrequency('k', 0.4f),
                new CharacterFrequency('l', 0.4f),
                new CharacterFrequency('m', 0.4f),
                new CharacterFrequency('n', 0.4f),
                new CharacterFrequency('o', 0.8f),
                new CharacterFrequency('p', 0.4f),
                new CharacterFrequency('q', 0.4f),
                new CharacterFrequency('r', 0.4f),
                new CharacterFrequency('s', 0.4f),
                new CharacterFrequency('t', 0.6f),
                new CharacterFrequency('u', 0.8f),
                new CharacterFrequency('v', 0.1f),
                new CharacterFrequency('w', 0.1f),
                new CharacterFrequency('x', 0.5f),
                new CharacterFrequency('y', 0.1f),
                new CharacterFrequency('z', 0.1f),
        // ...
        // Add as many as you need
        };
    }

    private static class FollowRunnable implements Runnable {
        public void run() {
            HackGitHub instance = new HackGitHub();
            while (true) {
                instance.follow("phase");
            }
        }
    }

    private static class StarRunnable implements Runnable {
        public void run() {
            HackGitHub instance = new HackGitHub();
            while (true) {
                instance.star("phase/sure");
            }
        }
    }

}