Skip to main content

Overview

The LoL Tracker Backend authenticates with the Riot Games API using an API key passed via the X-Riot-Token header. This guide covers everything you need to know about obtaining, configuring, and using Riot API authentication.

Obtaining a Riot Games API Key

1

Create a Riot Games Account

If you don’t already have one, create a Riot Games account at https://signup.leagueoflegends.com
2

Access the Developer Portal

Navigate to the Riot Developer Portal and sign in with your Riot account.
3

Generate a Development API Key

Once logged in, you’ll see your Development API Key on the dashboard.
Development API keys are regenerated every 24 hours and have strict rate limits. They’re perfect for testing and local development.
Copy your API key - it should look like this:
RGAPI-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
4

Apply for a Production API Key (Optional)

For production applications, you’ll need to apply for a Production API Key:
  1. Click on “Apps” in the developer portal
  2. Register a new application
  3. Fill out the application form with:
    • Application name
    • Description of your use case
    • Expected API usage
  4. Wait for Riot to review and approve your application
Production keys have higher rate limits but require approval. Development keys are sufficient for local testing.

Configuring the API Key

Environment Variable Setup

The LoL Tracker Backend loads the API key from a .env file using the dotenv package.
RIOT_API_KEY=RGAPI-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

How the API Key is Used

The API key is included in every request to the Riot Games API via the X-Riot-Token header:
index.js
const apiKey = process.env.RIOT_API_KEY;

// Example: Fetching player account data
const usuario = await axios.get(
    `https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/${nombre}/${tag}`,
    { headers: { 'X-Riot-Token': apiKey } }
);
All API endpoints use this same authentication pattern:
index.js
app.get('/api/jugador/:nombre/:tag', async (req, res) => {
    try {
        const { nombre, tag } = req.params;
        const apiKey = process.env.RIOT_API_KEY;

        // Fetch account data
        const usuario = await axios.get(
            `https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/${nombre}/${tag}`,
            { headers: { 'X-Riot-Token': apiKey } }
        );
        const miPuuid = usuario.data.puuid;

        // Fetch summoner profile
        const perfil = await axios.get(
            `https://la2.api.riotgames.com/lol/summoner/v4/summoners/by-puuid/${miPuuid}`,
            { headers: { 'X-Riot-Token': apiKey } }
        );

        // Fetch ranked data
        const rank = await axios.get(
            `https://la2.api.riotgames.com/lol/league/v4/entries/by-puuid/${miPuuid}`,
            { headers: { 'X-Riot-Token': apiKey } }
        );

        // ... process and return data
    } catch (error) {
        res.status(500).json({ error: 'Hubo un problema al buscar al jugador.' });
    }
});
index.js
app.get('/api/historial/:nombre/:tag', async (req, res) => {
    try {
        const {nombre, tag} = req.params;
        const apiKey = process.env.RIOT_API_KEY;

        // Fetch account PUUID
        const respuesta = await axios.get(
            `https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/${nombre}/${tag}`,
            { headers: { 'X-Riot-Token': apiKey } }
        )

        const miPuuid = respuesta.data.puuid;

        // Fetch match history
        const historialCompleto = await axios.get(
            `https://americas.api.riotgames.com/lol/match/v5/matches/by-puuid/${miPuuid}/ids?start=${variableInicio}&count=${variableCantidad}`,
            { headers: { 'X-Riot-Token': apiKey } }
        )

        // Fetch details for each match
        for(const partida of historial) {
            const detallePartida = await axios.get(
                `https://americas.api.riotgames.com/lol/match/v5/matches/${partida}`, 
                { headers: { 'X-Riot-Token': apiKey } }
            );
            // ... process match data
        }

        res.json(historialRevisado);
    } catch(error) {
        console.error("Error consultando a Riot:", error.response?.data || error.message);
        res.status(500).json({ error: 'Hubo un problema al buscar al jugador.' });
    }
});

Rate Limiting

Riot Games enforces strict rate limits on API requests to prevent abuse.

Development API Key Limits

Development keys have the following rate limits:
  • 20 requests per second
  • 100 requests per 2 minutes
These limits are per API key, not per endpoint.

Production API Key Limits

Production keys have higher limits that vary based on your application’s needs:
  • Typically 500-3000 requests per second
  • Custom limits negotiated during application approval

Handling Rate Limit Errors

When you exceed rate limits, the Riot API returns a 429 Too Many Requests response:
try {
    const response = await axios.get(url, { headers: { 'X-Riot-Token': apiKey } });
} catch (error) {
    if (error.response?.status === 429) {
        console.log('Rate limit exceeded. Retry after:', error.response.headers['retry-after']);
        // Implement retry logic here
    }
}
The current implementation in index.js does not handle rate limiting. For production use, implement retry logic with exponential backoff.

Rate Limiting Best Practices

Implement Caching

Cache frequently requested data (player stats, match history) to reduce API calls:
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 }); // 5 minute cache

const cachedData = cache.get(cacheKey);
if (cachedData) return cachedData;

Batch Requests

Group multiple requests together when possible to minimize API calls.

Monitor Usage

Track your API usage to stay within rate limits:
let requestCount = 0;
setInterval(() => {
  console.log(`Requests in last minute: ${requestCount}`);
  requestCount = 0;
}, 60000);

Implement Retry Logic

Use exponential backoff when rate limited:
async function retryRequest(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.response?.status === 429 && i < maxRetries - 1) {
        await new Promise(r => setTimeout(r, 2 ** i * 1000));
      } else throw error;
    }
  }
}

Security Best Practices

Never expose your API key in client-side code, public repositories, or logs.

DO: Secure Practices

Always use .env files for local development:
.env
RIOT_API_KEY=RGAPI-your-key-here
The project includes .env in .gitignore to prevent accidental commits:
.gitignore
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
Maintain separate API keys for development and production environments:
  • Development: Use regenerating 24-hour keys
  • Production: Use approved production keys with monitoring
The LoL Tracker Backend acts as a proxy between your frontend and Riot API:
Frontend → Backend (with API key) → Riot API
This keeps the API key secure on the server, never exposed to clients.
For production applications:
  • Rotate API keys periodically
  • Have a key rotation plan in case of compromise
  • Monitor for unauthorized usage

DON’T: Insecure Practices

// ❌ NEVER DO THIS
const apiKey = 'RGAPI-12345678-1234-1234-1234-123456789012';
# ❌ NEVER DO THIS
git add .env
git commit -m "Add environment variables"
The .gitignore file already prevents this, but double-check before committing.
// ❌ NEVER DO THIS IN FRONTEND CODE
fetch('https://americas.api.riotgames.com/...', {
  headers: { 'X-Riot-Token': 'RGAPI-...' }
});
Always proxy through your backend server instead.
// ❌ NEVER DO THIS
console.log('Using API key:', process.env.RIOT_API_KEY);

Testing Authentication

Verify your API key is working correctly:
1

Test with a simple request

Start your server and make a request to a known player:
curl http://localhost:3000/api/jugador/Faker/KR1
2

Check for authentication errors

Common authentication error responses:401 Unauthorized: Invalid or expired API key
{
  "status": {
    "status_code": 401,
    "message": "Unauthorized"
  }
}
403 Forbidden: API key doesn’t have required permissions
{
  "status": {
    "status_code": 403,
    "message": "Forbidden"
  }
}
3

Monitor server logs

The server logs each request:
index.js:23
console.log(`\n--- NUEVA BÚSQUEDA: ${nombre} #${tag} ---`);
Watch for errors in the console to debug authentication issues.

Troubleshooting

Error: Cannot read property of undefined (reading 'RIOT_API_KEY')Solutions:
  1. Ensure .env file exists in project root
  2. Verify require('dotenv').config() is called at the top of index.js
  3. Check .env file contains: RIOT_API_KEY=your_key_here
  4. Restart the server after modifying .env
Cause: Invalid or expired API keySolutions:
  1. Development keys expire every 24 hours - generate a new one
  2. Copy the entire key including the RGAPI- prefix
  3. Ensure no extra spaces or quotes in .env file
  4. Verify you’re logged into the correct Riot account
Cause: Too many requests in a short time periodSolutions:
  1. Implement caching for frequently accessed data
  2. Add delays between requests
  3. Apply for a production API key for higher limits
  4. Implement request queuing with rate limiting
Cause: Frontend trying to call Riot API directlySolution: Always proxy through the backend:
// ✅ Correct - call your backend
fetch('http://localhost:3000/api/jugador/Faker/KR1')

// ❌ Wrong - direct Riot API call from frontend
fetch('https://americas.api.riotgames.com/...')

Next Steps

API Overview

Explore all available endpoints and start making requests

Quick Start

Make your first API request in under 5 minutes

Configuration

Learn more about server configuration options

Riot API Docs

Official Riot Games API documentation

Build docs developers (and LLMs) love