Back to Crawl4ai

Stats

docs/md_v2/stats.md

0.8.618.0 KB
Original Source
<!-- Generated by scripts/update_stats.py — do not edit manually --> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script> <style> /* Hide the right-hand TOC sidebar and let content use full width */ #toc-sidebar { display: none !important; } .terminal-mkdocs-main-grid { margin-right: auto; } .terminal-mkdocs-main-content { max-width: 100%; } .stats-page { max-width: 1200px; margin: 0 auto; padding: 1rem 0; font-family: inherit; } .stats-header { text-align: center; margin-bottom: 2.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid #3f3f44; } .stats-header img { height: 48px; margin-bottom: 0.5rem; filter: drop-shadow(0 0 12px rgba(80, 255, 255, 0.3)); } .stats-header h1 { font-size: 1.8rem; color: #e8e9ed; margin: 0.5rem 0 0.25rem; letter-spacing: 0.5px; } .stats-header .subtitle { color: #a3abba; font-size: 0.95rem; } /* Metric Cards */ .metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2.5rem; } .metric-card { background: #1a1a1a; border: 1px solid #3f3f44; border-radius: 10px; padding: 1.25rem; text-align: center; transition: all 0.3s ease; position: relative; overflow: hidden; } .metric-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #50ffff, #f380f5); opacity: 0; transition: opacity 0.3s ease; } .metric-card:hover { transform: translateY(-4px); border-color: #50ffff; box-shadow: 0 8px 24px rgba(80, 255, 255, 0.12); } .metric-card:hover::before { opacity: 1; } .metric-value { font-size: 2rem; font-weight: 700; color: #50ffff; margin: 0.25rem 0; line-height: 1.2; } .metric-label { font-size: 0.8rem; color: #a3abba; text-transform: uppercase; letter-spacing: 1px; } .metric-sublabel { font-size: 0.75rem; color: #3f3f44; margin-top: 0.25rem; } /* Chart Sections */ .chart-section { background: #1a1a1a; border: 1px solid #3f3f44; border-radius: 10px; padding: 1.5rem; margin-bottom: 1.5rem; } .chart-section h2 { font-size: 1.1rem; color: #e8e9ed; margin: 0 0 1rem 0; padding-bottom: 0.75rem; border-bottom: 1px solid #3f3f44; } .chart-container { position: relative; width: 100%; height: 350px; } .chart-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem; } @media (max-width: 768px) { .stats-page { padding: 0.5rem 0.75rem; } .stats-header h1 { font-size: 1.4rem; } .chart-row { grid-template-columns: 1fr; } .metrics-grid { grid-template-columns: repeat(2, 1fr); gap: 0.6rem; } .metric-card { padding: 0.9rem 0.5rem; } .metric-value { font-size: 1.5rem; } .metric-label { font-size: 0.7rem; } .chart-container { height: 260px; } .chart-section { padding: 1rem; } } @media (max-width: 480px) { .metrics-grid { grid-template-columns: 1fr 1fr; gap: 0.5rem; } .metric-value { font-size: 1.25rem; } .metric-label { font-size: 0.65rem; letter-spacing: 0.5px; } .metric-sublabel { font-size: 0.65rem; } .chart-container { height: 220px; } .chart-section h2 { font-size: 0.95rem; } } /* Footer */ .stats-footer { text-align: center; padding: 1.5rem 0; margin-top: 1rem; border-top: 1px solid #3f3f44; color: #a3abba; font-size: 0.8rem; } </style> <div class="stats-page"> <div class="stats-header">
<h1>Growth</h1>
<div class="subtitle">Community growth & adoption metrics for Crawl4AI</div>
</div> <!-- Headline Metrics --> <div class="metrics-grid"> <div class="metric-card"> <div class="metric-label">GitHub Stars</div> <div class="metric-value">60,904</div> <div class="metric-sublabel">stargazers</div> </div> <div class="metric-card"> <div class="metric-label">Monthly Downloads</div> <div class="metric-value">914.2K</div> <div class="metric-sublabel">PyPI · latest month</div> </div> <div class="metric-card"> <div class="metric-label">Total Downloads</div> <div class="metric-value">9.72M</div> <div class="metric-sublabel">PyPI cumulative</div> </div> <div class="metric-card"> <div class="metric-label">Docker Pulls</div> <div class="metric-value">1.41M</div> <div class="metric-sublabel">hub.docker.com</div> </div> <div class="metric-card"> <div class="metric-label">Forks / Contributors</div> <div class="metric-value">6,217 <span style="color:#a3abba;font-size:1rem">/</span> 57</div> <div class="metric-sublabel">GitHub</div> </div> </div> <!-- Chart 1: Monthly PyPI Downloads (bar) --> <div class="chart-section"> <h2>PyPI Monthly Downloads</h2> <div class="chart-container"> <canvas id="monthlyChart"></canvas> </div> </div> <!-- Chart Row: Stars + Cumulative --> <div class="chart-row"> <div class="chart-section"> <h2>GitHub Star Growth</h2> <div class="chart-container"> <canvas id="starsChart"></canvas> </div> </div> <div class="chart-section"> <h2>Cumulative PyPI Downloads</h2> <div class="chart-container"> <canvas id="cumulativeChart"></canvas> </div> </div> </div> <!-- Chart Row: Daily + Traffic --> <div class="chart-row"> <div class="chart-section"> <h2>Daily Download Trend</h2> <div class="chart-container"> <canvas id="dailyChart"></canvas> </div> </div> <div class="chart-section"> <h2>GitHub Traffic (14 days)</h2> <div class="chart-container"> <canvas id="trafficChart"></canvas> </div> </div> </div> <div class="stats-footer"> Updated February 24, 2026 &middot; Data from GitHub API, PyPI Stats, Docker Hub </div> </div> <script> // --- Chart.js Global Config --- Chart.defaults.color = '#a3abba'; Chart.defaults.borderColor = '#3f3f44'; Chart.defaults.font.family = "'dm', Monaco, 'Courier New', monospace"; const CYAN = '#50ffff'; const CYAN_DIM = 'rgba(80,255,255,0.10)'; const CYAN_HOVER = '#0fbbaa'; const PINK = '#f380f5'; const PINK_DIM = 'rgba(243,128,245,0.10)'; const GRID_COLOR = '#3f3f44'; const TOOLTIP_BG = '#1a1a1a'; const tooltipStyle = { backgroundColor: TOOLTIP_BG, borderColor: CYAN, borderWidth: 1, titleColor: '#e8e9ed', bodyColor: '#a3abba', padding: 10, cornerRadius: 6, displayColors: false, }; const gridStyle = { color: GRID_COLOR, drawBorder: false }; const tickStyle = { color: '#a3abba', font: { size: 11 } }; // --- Data --- const monthlyLabels = ["2024-09", "2024-10", "2024-11", "2024-12", "2025-01", "2025-02", "2025-03", "2025-04", "2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10", "2025-11", "2025-12", "2026-01", "2026-02"]; const monthlyValues = [28000, 135000, 210000, 285000, 350000, 380000, 430000, 480000, 520000, 560000, 620000, 750000, 836245, 911467, 726475, 657370, 922296, 914168]; const starDates = ["2024-02-01", "2024-06-01", "2024-09-01", "2024-10-01", "2024-11-01", "2024-12-01", "2025-01-01", "2025-02-01", "2025-03-01", "2025-04-01", "2025-05-01", "2025-06-01", "2025-07-01", "2025-08-01", "2025-09-01", "2025-10-01", "2025-11-01", "2025-12-01", "2026-01-01", "2026-02-24"]; const starCounts = [0, 2000, 5000, 12000, 18000, 22000, 26000, 30000, 34000, 38000, 42000, 45000, 47000, 49000, 51000, 53000, 55000, 57000, 59000, 60904]; const cumulativeLabels = ["2024-09", "2024-10", "2024-11", "2024-12", "2025-01", "2025-02", "2025-03", "2025-04", "2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10", "2025-11", "2025-12", "2026-01", "2026-02"]; const cumulativePypi = [28000, 163000, 373000, 658000, 1008000, 1388000, 1818000, 2298000, 2818000, 3378000, 3998000, 4748000, 5584245, 6495712, 7222187, 7879557, 8801853, 9716021]; const dailyLabels = ["2025-08-27", "2025-08-28", "2025-08-29", "2025-08-30", "2025-08-31", "2025-09-01", "2025-09-02", "2025-09-03", "2025-09-04", "2025-09-05", "2025-09-06", "2025-09-07", "2025-09-08", "2025-09-09", "2025-09-10", "2025-09-11", "2025-09-12", "2025-09-13", "2025-09-14", "2025-09-15", "2025-09-16", "2025-09-17", "2025-09-18", "2025-09-19", "2025-09-20", "2025-09-21", "2025-09-22", "2025-09-23", "2025-09-24", "2025-09-25", "2025-09-26", "2025-09-27", "2025-09-28", "2025-09-29", "2025-09-30", "2025-10-01", "2025-10-02", "2025-10-03", "2025-10-04", "2025-10-05", "2025-10-06", "2025-10-07", "2025-10-08", "2025-10-09", "2025-10-10", "2025-10-11", "2025-10-12", "2025-10-13", "2025-10-14", "2025-10-15", "2025-10-16", "2025-10-17", "2025-10-18", "2025-10-19", "2025-10-20", "2025-10-21", "2025-10-22", "2025-10-23", "2025-10-24", "2025-10-25", "2025-10-26", "2025-10-27", "2025-10-28", "2025-10-29", "2025-10-30", "2025-10-31", "2025-11-01", "2025-11-02", "2025-11-03", "2025-11-04", "2025-11-05", "2025-11-06", "2025-11-07", "2025-11-08", "2025-11-09", "2025-11-10", "2025-11-11", "2025-11-12", "2025-11-13", "2025-11-14", "2025-11-15", "2025-11-16", "2025-11-17", "2025-11-18", "2025-11-19", "2025-11-20", "2025-11-21", "2025-11-22", "2025-11-23", "2025-11-24", "2025-11-25", "2025-11-26", "2025-11-27", "2025-11-28", "2025-11-29", "2025-11-30", "2025-12-01", "2025-12-02", "2025-12-03", "2025-12-04", "2025-12-05", "2025-12-06", "2025-12-07", "2025-12-08", "2025-12-09", "2025-12-10", "2025-12-11", "2025-12-12", "2025-12-13", "2025-12-14", "2025-12-15", "2025-12-16", "2025-12-17", "2025-12-18", "2025-12-19", "2025-12-20", "2025-12-21", "2025-12-22", "2025-12-23", "2025-12-24", "2025-12-25", "2025-12-26", "2025-12-27", "2025-12-28", "2025-12-29", "2025-12-30", "2025-12-31", "2026-01-01", "2026-01-02", "2026-01-03", "2026-01-04", "2026-01-05", "2026-01-06", "2026-01-07", "2026-01-08", "2026-01-09", "2026-01-10", "2026-01-11", "2026-01-12", "2026-01-13", "2026-01-14", "2026-01-15", "2026-01-16", "2026-01-17", "2026-01-18", "2026-01-19", "2026-01-20", "2026-01-21", "2026-01-22", "2026-01-23", "2026-01-24", "2026-01-25", "2026-01-26", "2026-01-27", "2026-01-28", "2026-01-29", "2026-01-30", "2026-01-31", "2026-02-01", "2026-02-02", "2026-02-03", "2026-02-04", "2026-02-05", "2026-02-06", "2026-02-07", "2026-02-08", "2026-02-09", "2026-02-10", "2026-02-11", "2026-02-12", "2026-02-13", "2026-02-14", "2026-02-15", "2026-02-16", "2026-02-17", "2026-02-18", "2026-02-19", "2026-02-20", "2026-02-21", "2026-02-22", "2026-02-23"]; const dailyValues = [36852, 29139, 26202, 14515, 12717, 30212, 26723, 36263, 30947, 21856, 12788, 16109, 33670, 38096, 38520, 32210, 32645, 16740, 15665, 33468, 35826, 37881, 38822, 34382, 12228, 15941, 34119, 32959, 33236, 29592, 27001, 14190, 11923, 28881, 33352, 29133, 22553, 20377, 10201, 18760, 28627, 26443, 33205, 30002, 37306, 24336, 19082, 28941, 27498, 36493, 30912, 28221, 26990, 41450, 69663, 45509, 37775, 30266, 24564, 12144, 14088, 28156, 32380, 32150, 32103, 32139, 15927, 14829, 25046, 34682, 36734, 24177, 27621, 18836, 17588, 23041, 24663, 32488, 35575, 24627, 11902, 22698, 26320, 27062, 33285, 28878, 37767, 14090, 13125, 25697, 28261, 32016, 25571, 22364, 11104, 10501, 23124, 25857, 24070, 27150, 22595, 12676, 18075, 25277, 33018, 33318, 26019, 21790, 11025, 12901, 21774, 29209, 32380, 24685, 22711, 22882, 13627, 22852, 20014, 23430, 12401, 14902, 11492, 12861, 18941, 19171, 17143, 11321, 16012, 13309, 14477, 28824, 28074, 25749, 26326, 32618, 25266, 31603, 33214, 40930, 34411, 34820, 32173, 23178, 29160, 46329, 34716, 37425, 39073, 36770, 20527, 25662, 33863, 37671, 43628, 34239, 29112, 21816, 28222, 41988, 57712, 43590, 43377, 38494, 27584, 26270, 36057, 51525, 48067, 47749, 42424, 29999, 28833, 43076, 39635, 42221, 42354, 43540, 38995, 32268, 40188]; const trafficDates = ["2026-02-10", "2026-02-11", "2026-02-12", "2026-02-13", "2026-02-14", "2026-02-15", "2026-02-16", "2026-02-17", "2026-02-18", "2026-02-19", "2026-02-20", "2026-02-21", "2026-02-22", "2026-02-23"]; const trafficViews = [3012, 5764, 4431, 1974, 2246, 1647, 1627, 2638, 4650, 5464, 3370, 2275, 2702, 4372]; const trafficUniques = [1698, 2863, 2082, 1014, 1098, 1014, 1093, 1597, 1610, 1554, 1374, 1182, 1595, 2344]; function shortMonth(label) { const parts = label.split('-'); const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; return months[parseInt(parts[1])-1] + ' ' + parts[0].slice(2); } function shortDate(label) { const parts = label.split('-'); const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; return months[parseInt(parts[1])-1] + ' ' + parts[2]; } function fmtK(val) { if (val >= 1000000) return (val/1000000).toFixed(1) + 'M'; if (val >= 1000) return (val/1000).toFixed(0) + 'K'; return val; } // --- Chart 1: Monthly Downloads (bar) --- new Chart(document.getElementById('monthlyChart'), { type: 'bar', data: { labels: monthlyLabels.map(shortMonth), datasets: [{ label: 'Downloads', data: monthlyValues, backgroundColor: CYAN, hoverBackgroundColor: CYAN_HOVER, borderRadius: 4, borderSkipped: false, }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { ...tooltipStyle, callbacks: { label: ctx => fmtK(ctx.raw) + ' downloads' } } }, scales: { x: { grid: { display: false }, ticks: tickStyle }, y: { grid: gridStyle, ticks: { ...tickStyle, callback: fmtK } } } } }); // --- Chart 2: Star Growth (area) --- new Chart(document.getElementById('starsChart'), { type: 'line', data: { labels: starDates.map(shortMonth), datasets: [{ label: 'Stars', data: starCounts, borderColor: CYAN, backgroundColor: CYAN_DIM, fill: true, tension: 0.35, pointRadius: 3, pointBackgroundColor: CYAN, pointHoverRadius: 6, }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { ...tooltipStyle, callbacks: { label: ctx => fmtK(ctx.raw) + ' stars' } } }, scales: { x: { grid: { display: false }, ticks: { ...tickStyle, maxTicksLimit: 8 } }, y: { grid: gridStyle, ticks: { ...tickStyle, callback: fmtK } } } } }); // --- Chart 3: Cumulative Downloads (area) --- new Chart(document.getElementById('cumulativeChart'), { type: 'line', data: { labels: cumulativeLabels.map(shortMonth), datasets: [{ label: 'Cumulative PyPI', data: cumulativePypi, borderColor: PINK, backgroundColor: PINK_DIM, fill: true, tension: 0.35, pointRadius: 3, pointBackgroundColor: PINK, pointHoverRadius: 6, }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { ...tooltipStyle, callbacks: { label: ctx => fmtK(ctx.raw) + ' total downloads' } } }, scales: { x: { grid: { display: false }, ticks: tickStyle }, y: { grid: gridStyle, ticks: { ...tickStyle, callback: fmtK } } } } }); // --- Chart 4: Daily Downloads (area) --- (function() { // Sample daily data to avoid overcrowding (show every 7th day) const step = Math.max(1, Math.floor(dailyLabels.length / 60)); const sampledLabels = dailyLabels.filter((_, i) => i % step === 0); const sampledValues = dailyValues.filter((_, i) => i % step === 0); new Chart(document.getElementById('dailyChart'), { type: 'line', data: { labels: sampledLabels.map(shortDate), datasets: [{ label: 'Daily Downloads', data: sampledValues, borderColor: CYAN, backgroundColor: CYAN_DIM, fill: true, tension: 0.3, pointRadius: 0, borderWidth: 1.5, }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { ...tooltipStyle, callbacks: { label: ctx => fmtK(ctx.raw) + ' downloads' } } }, scales: { x: { grid: { display: false }, ticks: { ...tickStyle, maxTicksLimit: 8 } }, y: { grid: gridStyle, ticks: { ...tickStyle, callback: fmtK }, beginAtZero: true } } } }); })(); // --- Chart 5: GitHub Traffic (dual bar) --- new Chart(document.getElementById('trafficChart'), { type: 'bar', data: { labels: trafficDates.map(shortDate), datasets: [ { label: 'Page Views', data: trafficViews, backgroundColor: CYAN, hoverBackgroundColor: CYAN_HOVER, borderRadius: 4, borderSkipped: false, }, { label: 'Unique Visitors', data: trafficUniques, backgroundColor: PINK, hoverBackgroundColor: '#d060d0', borderRadius: 4, borderSkipped: false, } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { labels: { color: '#a3abba', boxWidth: 12, padding: 16 } }, tooltip: tooltipStyle, }, scales: { x: { grid: { display: false }, ticks: tickStyle }, y: { grid: gridStyle, ticks: tickStyle } } } }); </script>