Avoiding GitHub API Rate Limits When Running Composer

If you’ve ever run composer install or composer update only to be greeted by:

API rate limit exceeded for x.x.x.x.

or had Composer suddenly stop and ask you for a GitHub OAuth token, you’re bumping into the same underlying issue: GitHub’s API limits.

These limits kick in even when you’re working with public repositories, and they’re especially common when Composer has to resolve many dependencies or access GitHub repeatedly during installs.

Table of Contents

Why It Happens

Composer fetches package metadata from GitHub’s API. When it does this anonymously (without a token), GitHub grants only 60 requests per hour per IP — not remotely enough for large projects, fresh setups, or CI/CD pipelines.

As soon as Composer exceeds that quota, you’ll see the “API rate limit exceeded” error or get prompted for a GitHub token.

Even public repositories hit the same limit, because GitHub throttles unauthenticated API access.

With a GitHub token, the limit jumps to 5,000 requests per hour, which is more than enough for typical Composer operations.

The Fix: Add a GitHub Token

Generate a GitHub Personal Access Token (fine-grained recommended).
If you only need public package access, you can even use a token with no scopes.
If you need private repos, make sure it includes:

  • read:packages
  • read:repo

Then tell Composer to use it:

composer config -g --auth github-oauth.github.com <GITHUB_PAT>

This stores your token in Composer’s global auth.json:

~/.composer/auth.json

Once set, Composer stops prompting for tokens, stops falling back to source clones, and stops hitting anonymous rate limits.

Using composer install --no-interaction

A workaround to the GitHub’s API limit issue is using composer install --no-interaction

There’s a surprisingly important difference between running Composer interactively and non-interactively — and it directly affects how you experience GitHub API limits.

composer install

When you run Composer normally, it is allowed to ask you for input.
So when GitHub rate limits you, Composer stops and displays something like:

API rate limit exceeded for x.x.x.x.
Please create a GitHub OAuth token...
Token (hidden):

Because it’s interactive, Composer waits for you to paste a token before continuing.
This is why you see the rate-limit error explicitly.

composer install --no-interaction

When you add --no-interaction, Composer is not allowed to prompt you.
So the moment it hits GitHub’s API rate limits, it takes a different path:

  1. It tries anonymous access → GitHub blocks it
  2. Since Composer cannot ask for a token, it skips the prompt entirely
  3. Composer immediately falls back to a slower but API-free method:
    cloning dependencies via Git instead of downloading dist archives

This means:

  • You don’t see the “API rate limit exceeded” message
  • Composer still installs your dependencies, just using Git clones
  • You end up with a long stream of messages like:
  Failed to download ... Could not authenticate against github.com
  Now trying to download from source

That fallback mechanism bypasses the GitHub API entirely, which is why the install completes without asking for authentication.

Avoiding prompts doesn’t solve the rate-limit problem

composer install --no-interaction doesn’t solve the rate-limit problem — it simply avoids it by switching to a non-API method of downloading packages.

It works, but:

  • It’s slower
  • It’s noisy
  • Git clones can be inconsistent
  • And it hides the real cause (missing authentication)

If you also don’t have a composer.lock file, installs trigger dependency resolution, which increases GitHub API usage even more — making the fallback even more likely.

Best Practices

Commit your composer.lock

This dramatically reduces the number of GitHub API calls during installs.

Without a composer.lock file, composer must query GitHub for version metadata for every package, often triggering the 60-requests-per-hour anonymous limit. With a composer.lock file, composer doesn’t need to resolve dependencies, it simply installs the exact versions listed—no metadata lookups, no heavy API usage, and far fewer chances of hitting rate limits.

Use environment variables

Instead of pasting a token:

composer config -g --auth github-oauth.github.com "$GITHUB_PAT"

In CI/CD pipelines

Use:

composer install --no-interaction --prefer-dist --no-progress

And inject your token as a secret:

COMPOSER_AUTH='{"github-oauth":{"github.com":"'"$GITHUB_PAT"'"}}' \
composer install --no-interaction

This avoids storing credentials on disk and keeps builds stable.

Rotate tokens regularly

It’s easy to forget these live in plain text in auth.json. Treat them like passwords.

Final Thoughts

GitHub’s API limits aren’t errors — they’re guardrails.
Once Composer has a token and a lock file to work with, installs run faster, quieter, and without interruptions, whether you’re working locally or deploying in CI.

Leave a Reply

Navigation

About

Writing on the Wall is a newsletter for freelance writers seeking inspiration, advice, and support on their creative journey.

Discover more from JuanMa Codes

Subscribe now to keep reading and get access to the full archive.

Continue reading