Skip to content

Instantly share code, notes, and snippets.

@JakubAndrysek
Last active February 17, 2025 22:09
Show Gist options
  • Save JakubAndrysek/d42434f13258d4f4f2f25a19120f6514 to your computer and use it in GitHub Desktop.
Save JakubAndrysek/d42434f13258d4f4f2f25a19120f6514 to your computer and use it in GitHub Desktop.
PyPI user statistics - all downloads

PyPI user statistics - all downloads

This API tool allows users to retrieve the total downloads for specific PyPI projects, with options for caching and formatted outputs.

Features

  • Fetches download statistics for PyPI projects (mkdoxy and pyspacemouse by default).
  • Caches API responses to reduce load (revalidates every 12 hours).
  • Supports forced revalidation using a query parameter.
  • Outputs download statistics in human-readable formats (e.g., 100k, 1.2M).
  • Provides clean URLs for API access.

Use with shields.io

<img alt="Total downloads" src="https://img.shields.io/badge/dynamic/json?url=<URL>&query=%24.total_downloads_formatted&suffix=%20downloads&style=flat-square&logo=python&label=PyPI&cacheSeconds=1&link=https%3A%2F%2Fpypi.org%2Fuser%2Fkuband%2F">
<?php
// Set headers for JSON response
header('Content-Type: application/json');
// Configuration
$apiUrl = 'https://api.pepy.tech/api/v2/projects/';
$projects = ['mkdoxy', 'pyspacemouse'];
$apiKey = 'API';
$cacheFile = 'cache.json';
$cacheDuration = 12 * 60 * 60; // 12 hours in seconds
// Check if force revalidation is requested
$forceRevalidate = isset($_GET['force']) && $_GET['force'] === 'true';
// Function to fetch project data from API
function fetchProjectData($apiUrl, $project, $apiKey) {
$url = $apiUrl . $project;
// Create context with headers
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => "X-API-Key: $apiKey\r\n"
]
]);
$response = file_get_contents($url, false, $context);
if ($response === FALSE) {
return ['error' => 'Error fetching data'];
}
return json_decode($response, true);
}
// Function to format numbers
function formatNumber($number) {
if ($number >= 1000000) {
return round($number / 1000000, 1) . 'M';
} elseif ($number >= 1000) {
return round($number / 1000, 1) . 'k';
}
return $number;
}
// Determine if cache needs to be updated
$cacheValid = file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $cacheDuration;
if (!$cacheValid || $forceRevalidate) {
// Initialize result array
$totalDownloads = 0;
$result = [
'total_downloads' => 0,
'total_downloads_formatted' => '',
'projects' => [],
'last_fetch_time' => date('Y-m-d H:i:s')
];
// Fetch data for each project
foreach ($projects as $project) {
$data = fetchProjectData($apiUrl, $project, $apiKey);
if (isset($data['total_downloads'])) {
$projectDownloads = $data['total_downloads'];
$totalDownloads += $projectDownloads;
$result['projects'][$project] = [
'total_downloads' => $projectDownloads,
'total_downloads_formatted' => formatNumber($projectDownloads)
];
} else {
$result['projects'][$project] = [
'error' => $data['error'] ?? 'No data found'
];
}
}
// Set total downloads in the result
$result['total_downloads'] = $totalDownloads;
$result['total_downloads_formatted'] = formatNumber($totalDownloads);
// Save result to cache
file_put_contents($cacheFile, json_encode($result, JSON_PRETTY_PRINT));
} else {
// Load cached data
$result = json_decode(file_get_contents($cacheFile), true);
}
// Return JSON response
echo json_encode($result, JSON_PRETTY_PRINT);
{
"total_downloads": 760780,
"total_downloads_formatted": "760.8k",
"projects": {
"mkdoxy": {
"total_downloads": 214844,
"total_downloads_formatted": "214.8k"
},
"pyspacemouse": {
"total_downloads": 192256,
"total_downloads_formatted": "192.3k"
},
"mkdocs-open-in-new-tab": {
"total_downloads": 325968,
"total_downloads_formatted": "326k"
},
"mkdocs-auto-refresh-build-pages": {
"total_downloads": 1772,
"total_downloads_formatted": "1.8k"
},
"mkdocs-typedoc": {
"total_downloads": 11390,
"total_downloads_formatted": "11.4k"
},
"mkdocs-zip-folders": {
"total_downloads": 7642,
"total_downloads_formatted": "7.6k"
},
"mkdocs-resize-images": {
"total_downloads": 6908,
"total_downloads_formatted": "6.9k"
}
},
"last_fetch_time": "2024-12-08 13:45:17"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment