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
- The Fix: Add a GitHub Token
- Using composer install –no-interaction
- Best Practices
- Final Thoughts
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:packagesread: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.jsonOnce 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:
- It tries anonymous access → GitHub blocks it
- Since Composer cannot ask for a token, it skips the prompt entirely
- 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 sourceThat 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-progressAnd inject your token as a secret:
COMPOSER_AUTH='{"github-oauth":{"github.com":"'"$GITHUB_PAT"'"}}' \
composer install --no-interactionThis 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