A comprehensive TypeScript framework for streaming, analyzing, and visualizing FiveM server data with real-time analytics, country-based analysis, and beautiful console reporting.
# Install dependencies
bun install
# Run basic example (Thai servers with colored output)
bun run example.ts
# Run full analysis with charts
bun run analysis.ts
# Run chart demo
bun run analysis.ts --demo- Bun runtime (recommended) or Node.js 18+
- TypeScript support
git clone <repository-url>
cd fivem-server-list
bun installsrc/
├── types/ # TypeScript definitions
│ └── index.ts # Core interfaces (ServerInfo, ServerData, etc.)
├── decoder/ # Manual protobuf decoding
│ └── ProtobufDecoder.ts
├── stream/ # Stream processing
│ └── FrameReader.ts
├── client/ # Main API client
│ └── FiveMServerStream.ts
├── analyzer/ # Data analysis engine
│ └── ServerAnalyzer.ts
├── formatter/ # Report formatting
│ └── ReportFormatter.ts
├── utils/ # Utilities (charts, colors)
│ └── ConsoleChart.ts
└── index.ts # Main exports
examples/
├── example.ts # Basic usage example
├── analysis.ts # Full analysis with charts
└── README.md # This documentation
- Live Data: Stream FiveM server data in real-time
- Efficient: Manual protobuf decoding without schema generation
- Configurable: Adjustable timeframe and server limits
- Error Handling: Robust error handling and recovery
- Locale-based: Primary detection using
server.vars.locale - IP Geolocation: Fallback IP-based country detection
- Domain Analysis: TLD-based country mapping
- 99+ Countries: Comprehensive country support with flag emojis
- Server Statistics: Player counts, capacity, versions
- Game Type Analysis: Popular game modes and frameworks
- Geographic Distribution: Country-wise server distribution
- Performance Metrics: Average population, server efficiency
- Operating System Detection: Server OS identification
- Real-time Charts: Horizontal bars, pie charts, tables
- Progress Tracking: Live progress bars during data collection
- Color-coded Output: ANSI colors and FiveM color code support
- Flag Emojis: Country flags for better visualization
The main client for streaming FiveM server data.
new FiveMServerStream(config: FiveMStreamConfig)Config Options:
interface FiveMStreamConfig {
streamSince?: number; // Seconds to look back (default: 300)
maxServers?: number; // Max servers to process
handlers?: StreamEventHandlers; // Event callbacks (optional)
}Starts the server data stream.
const client = new FiveMServerStream({ streamSince: 300 });
await client.start();Collects all servers and returns them as a Promise.
const servers = await client.getAllServers();
console.log(`Found ${servers.length} servers`);Collects servers matching the filter criteria.
// Get Thai servers only
const thaiServers = await client.getFilteredServers(
server => server.Data?.vars?.locale === "th-TH"
);
// Get high-population servers
const popularServers = await client.getFilteredServers(
server => (server.Data?.clients || 0) > 50
);Stops the stream.
Returns the number of processed servers.
Returns whether the stream is currently active.
Advanced data analysis engine for server statistics.
Adds a server to the analysis dataset.
Adds multiple servers to the analysis.
Performs comprehensive analysis and returns detailed report.
const analyzer = new ServerAnalyzer();
servers.forEach(server => analyzer.addServer(server));
const report = analyzer.analyze();
console.log(`Analyzed ${report.overview.totalServers} servers`);
console.log(`Found ${report.byCountry.length} countries`);Clears all collected data.
Returns current server count in analyzer.
Static utility class for formatting analysis reports.
Generates comprehensive report with charts and statistics.
Generates concise summary report.
Generates country-focused report.
Formats overview statistics section.
Formats detailed country analysis.
Utility class for creating beautiful console charts.
Creates horizontal bar chart.
const gameTypes = { "ESX Legacy": 450, "Freeroam": 280, "Racing": 150 };
console.log(ConsoleChart.horizontalBar(gameTypes, {
title: '🎮 Popular Game Types',
maxWidth: 40,
colors: true
}));Creates ASCII pie chart representation.
Creates formatted table with proper alignment.
Creates progress bar with percentage.
Creates mini sparkline chart.
import { FiveMServerStream } from './src/index.js';
const client = new FiveMServerStream({
streamSince: 600, // 10 minutes of data
maxServers: 1000 // Process up to 1000 servers
});
const servers = await client.getAllServers();
console.log(`Found ${servers.length} servers`);const client = new FiveMServerStream({
handlers: {
onServer: (server) => {
console.log(`${server.EndPoint}: ${server.Data?.clients || 0} players`);
},
onError: (error) => {
console.error('Stream error:', error.message);
},
onEnd: () => {
console.log('Stream completed');
}
}
});
await client.start();// Multi-criteria filtering
const targetServers = await client.getFilteredServers(server => {
const data = server.Data;
return data?.vars?.locale?.startsWith('en') && // English locales
(data?.clients || 0) > 20 && // 20+ players
data?.gametype?.includes('Roleplay'); // Roleplay servers
});import { ServerAnalyzer, ReportFormatter } from './src/index.js';
const analyzer = new ServerAnalyzer();
const servers = await client.getAllServers();
analyzer.addServers(servers);
const report = analyzer.analyze();
// Show top countries by player count
report.byCountry
.sort((a, b) => b.playerCount - a.playerCount)
.slice(0, 10)
.forEach((country, i) => {
console.log(`${i+1}. ${country.country}: ${country.playerCount} players`);
});The framework supports FiveM color codes in server names and converts them to ANSI colors:
// FiveM Color Codes → ANSI Colors
^0 → Black ^5 → Cyan
^1 → Red ^6 → Magenta
^2 → Green ^7 → White
^3 → Yellow ^8 → Dark Gray
^4 → Blue ^9 → Light RedExample usage:
function parseFiveMColors(text: string): string {
const colorMap = {
'^0': '\x1b[30m', '^1': '\x1b[31m', '^2': '\x1b[32m',
'^3': '\x1b[33m', '^4': '\x1b[34m', '^5': '\x1b[36m',
'^6': '\x1b[35m', '^7': '\x1b[37m', '^8': '\x1b[90m',
'^9': '\x1b[91m'
};
let result = text;
Object.entries(colorMap).forEach(([code, ansi]) => {
result = result.replace(new RegExp(code.replace('^', '\\^'), 'g'), ansi);
});
return result + '\x1b[0m'; // Reset color
}The framework supports 50+ countries with automatic detection via:
- Format:
language-COUNTRYorlanguage_COUNTRY - Examples:
th-TH,en-US,de-DE,fr-FR - Coverage: 100+ locale combinations
- Method: IP range analysis
- Coverage: Major countries and regions
- Accuracy: ~85% for major providers
- Method: TLD analysis (.th, .us, .de, etc.)
- Coverage: Country-code TLDs
- Accuracy: ~70% (many use .com)
🇹🇭 Thailand • 🇺🇸 United States • 🇬🇧 United Kingdom • 🇩🇪 Germany • 🇫🇷 France • 🇯🇵 Japan • 🇦🇺 Australia • 🇨🇦 Canada • 🇧� Brazil • 🇷🇺 Russia • 🇨🇳 China • 🇰🇷 South Korea • 🇪🇸 Spain • 🇮🇹 Italy • 🇳🇱 Netherlands • 🇸🇪 Sweden • 🇵🇱 Poland • 🇹🇷 Turkey • 🇮🇳 India • 🇻🇳 Vietnam • 🇲🇾 Malaysia • 🇮🇩 Indonesia • 🇵🇭 Philippines • 🇸🇬 Singapore • 🇲🇽 Mexico • 🇦🇷 Argentina • 🇵🇹 Portugal
interface ServerInfo {
EndPoint?: string; // Server IP:Port
Data?: ServerData; // Server details
}
interface ServerData {
svMaxclients?: number; // Max player slots
clients?: number; // Current players
protocol?: number; // Protocol version
hostname?: string; // Server name
gametype?: string; // Game mode
mapname?: string; // Current map
resources?: string[]; // Loaded resources
server?: string; // Server version
players?: Player[]; // Player list
vars?: { [key: string]: string }; // Server variables
enhancedHostSupport?: boolean;
upvotePower?: number;
connectEndPoints?: string[];
burstPower?: number;
}
interface Player {
name?: string;
identifiers?: string[];
endpoint?: string;
ping?: number;
id?: number;
}interface AnalysisReport {
overview: ServerStats; // Overall statistics
byCountry: CountryStats[]; // Country breakdown
timestamp: Date; // Analysis time
analysisTime: number; // Processing time (ms)
}
interface ServerStats {
totalServers: number;
totalPlayers: number;
totalMaxSlots: number;
averagePopulation: number;
popularGameTypes: { [key: string]: number };
popularMaps: { [key: string]: number };
serverVersions: { [key: string]: number };
protocolVersions: { [key: string]: number };
operatingSystems: { [key: string]: number };
resourceUsage: {
totalResources: number;
averageResourcesPerServer: number;
popularResources: { [key: string]: number };
};
}
interface CountryStats {
country: string;
serverCount: number;
playerCount: number;
averagePopulation: number;
topGameTypes: string[];
topServers: Array<{
endpoint: string;
hostname: string;
players: number;
maxSlots: number;
}>;
}import { FiveMServerStream } from './src/index.js';
async function getServerList() {
const client = new FiveMServerStream({
streamSince: 300,
maxServers: 100
});
const servers = await client.getAllServers();
servers.forEach((server, i) => {
console.log(`${i+1}. ${server.Data?.hostname || 'Unknown'}`);
console.log(` Players: ${server.Data?.clients || 0}/${server.Data?.svMaxclients || 0}`);
});
}import { FiveMServerStream, ServerAnalyzer, ReportFormatter } from './src/index.js';
async function analyzeByCountry() {
const client = new FiveMServerStream({ maxServers: 500 });
const analyzer = new ServerAnalyzer();
const servers = await client.getAllServers();
analyzer.addServers(servers);
const report = analyzer.analyze();
console.log(ReportFormatter.formatCountrySummary(report.byCountry));
}async function streamWithProgress() {
let count = 0;
const client = new FiveMServerStream({
maxServers: 1000,
handlers: {
onServer: (server) => {
count++;
process.stdout.write(`\rProcessed: ${count} servers`);
},
onEnd: () => {
console.log(`\nCompleted! Found ${count} servers`);
}
}
});
await client.start();
}async function customAnalysis() {
const client = new FiveMServerStream({ maxServers: 2000 });
const servers = await client.getAllServers();
// Find most popular resources
const resourceCount: { [key: string]: number } = {};
servers.forEach(server => {
server.Data?.resources?.forEach(resource => {
resourceCount[resource] = (resourceCount[resource] || 0) + 1;
});
});
const topResources = Object.entries(resourceCount)
.sort(([,a], [,b]) => b - a)
.slice(0, 10);
console.log('Top 10 Resources:');
topResources.forEach(([resource, count], i) => {
console.log(`${i+1}. ${resource}: ${count} servers`);
});
}const client = new FiveMServerStream({
streamSince: 60, // Shorter timeframe = less data
maxServers: 500, // Limit processing for faster results
});const client = new FiveMServerStream({
handlers: {
onError: (error) => {
console.error('Stream error:', error.message);
// Implement retry logic or fallback
}
}
});const analyzer = new ServerAnalyzer();
// Process in batches to avoid memory issues
const batchSize = 100;
for (let i = 0; i < servers.length; i += batchSize) {
const batch = servers.slice(i, i + batchSize);
analyzer.addServers(batch);
if (i % 500 === 0) {
// Periodic analysis to free memory
const report = analyzer.analyze();
analyzer.clear();
}
}1. Empty Results
// Check if stream is completing properly
const client = new FiveMServerStream({
handlers: {
onEnd: () => console.log('Stream completed successfully'),
onError: (e) => console.error('Stream failed:', e)
}
});2. Memory Issues with Large Datasets
- Use
maxServersto limit data - Process in smaller batches
- Clear analyzer periodically
3. Network Timeouts
- Reduce
maxServers - Implement retry logic
- Check network connectivity
4. Incorrect Country Detection
- Verify locale data exists:
server.Data?.vars?.locale - Check IP format for fallback detection
- Report missing countries for updates
| Servers | Processing Time | Memory Usage |
|---|---|---|
| 100 | ~200ms | ~50MB |
| 500 | ~800ms | ~150MB |
| 1,000 | ~1.5s | ~250MB |
| 5,000 | ~6s | ~800MB |
Tested on modern hardware with good internet connection
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- FiveM team for the server list API
- Community for feedback and feature requests
- Contributors who helped improve the framework
Made with B3sty❤️ for the FiveM community