How To Get Millions Of Downloads On Your NPM Package

How To Get Millions Of Downloads On Your NPM Package

Download the npm-downloads-increaser package and run from the command line. Capable of handling 100+ downloads/second.

What does it do?

It’s like running npm install -g <my package> over and over again, as fast as possible. This will increase the number of Weekly Downloads for your package on npmJS.

Turning this:

NPMJS Weekly Download count - low

Into this:

NPMJS Weekly Download count - high

The changes in download numbers will also propagate to other package managers, such as yarnpkg.

YarnPKG Monthly Download count - high

Why should I use this?

  • It increases the popularity score of your NPM package, which increases its package score via the npms.io ranking algorithm
  • Packages with a higher popularity score have increased visibility on npmJS
  • Some users are more likely to download a package that already has a high number of weekly downloads

Why shouldn’t I use this?

  • It wastes the resources of npmJS, an open source company.
  • npmJS shows weekly downloads only. You would need to run this regularly to keep the weekly downloads high.
  • Weekly downloads is not an accurate measure of the value of an NPM package.
  • Faking the popularity of your own NPM package is kinda cringe.

How do I use this?

Install npm-downloads-increaser globally:

npm i -g npm-downloads-increaser

Then start increasing your downloads:

npm-downloads-increaser

You will then be prompted to set some configurations:

PropertyDescriptionExample
packageNameNPM package to increase the downloads ofnpm-downloads-increaser
numDownloadsNumber of times to download the package100000
maxConcurrentDownloadsAmount of downloads to run in parallel at once300
downloadTimeoutMax time (in ms) to wait for for a download to complete3000

You should experiment with different values for maxConcurrentDownloads and downloadTimeout to find the combination which maximises the download rate for your package. By default these values are set to 300 and 3000 respectively. These values resulted in an average download rate of 40dl/s when targeting a 20kB package from my computer.

In general, you will want a lower maxConcurrentDownloads or higher downloadTimeout if:

  • Your package is large in size
  • Your network is slow

How does it work?

First we must determine a valid package version. This can be done by querying the npms.io database, as the response will include the latest version number of the specified package. For this, we use queryNpms():

const queryNpms = async (): Promise<NpmjsResponse> => {
    const npmsResponse: GaxiosResponse<NpmjsResponse> = await request<NpmjsResponse>({
        baseUrl: "https://api.npms.io",
        url: `/v2/package/${getConfig().packageName}`,
        method: "GET",
    }).catch((response: GaxiosError<NpmjsResponse>) => {
        throw Error(`Failed to download ${response.config.url}\n${response.message}`);
    });

    return npmsResponse.data;
};

Now that we have a valid package version, we can construct the download URL for npmJS. The downloadPackage() method behaves similarly to npm install <my package>, and will increment the number of downloads for your package by +1.

downloadTimeout specifies the maximum time to wait for the download to succeed. If the download times out, or fails for any other reason, then it is discarded.

const downloadPackage = async (version: string, stats: Stats): Promise<unknown> => {
    return request<unknown>({
        baseUrl: "https://registry.npmjs.com",
        url: `/${getConfig().packageName}/-/${getConfig().packageName}-${version}.tgz`,
        method: "GET",
        timeout: getConfig().downloadTimeout,
        responseType: "stream",
    })
        .then((_) => {
            stats.successfulDownloads++;
        })
        .catch((_) => {
            stats.failedDownloads++;
        });
};

To increment the number of downloads on your package as fast as possible, we use the spamDownloads() method. This generates maxConcurrentDownloads http requests and executes them in parallel using Promise.all().

It will then check whether the number of successful downloads has exceeded your specified numDownloads. If not, then it will run again recursively.

const spamDownloads = async (version: string, stats: Stats): Promise<void> => {
    const requests: Promise<unknown>[] = [];

    for (let i = 0; i < getConfig().maxConcurrentDownloads; i++) {
        requests.push(downloadPackage(version, stats));
    }

    await Promise.all(requests);

    if (stats.successfulDownloads < getConfig().numDownloads) {
        await spamDownloads(version, stats);
    }
};

All of this is brought together using run(), which is executed upon starting npm-downloads-increaser.

setInterval(() => logDownload(stats), 1000) will update the console with the package download statistics every 1000ms. These statistics include:

  • Download count
  • Download speed
  • Estimated time remaining
const run = async (): Promise<void> => {
    try {
        const npmsResponse: NpmjsResponse = await queryNpms();
        const version: string = npmsResponse.collected.metadata.version;
        const startTime = Date.now();
        const stats: Stats = new Stats(startTime);

        const loggingInterval: NodeJS.Timeout = setInterval(() => logDownload(stats), 1000);
        await spamDownloads(version, stats);

        clearInterval(loggingInterval);
        logComplete();
    } catch (e) {
        logError(e);
    }
};

Demo

Demo

View this package on npmJS here, or check out the source code here.

Leave a Reply

Your email address will not be published. Required fields are marked *