Fetching 24-Hour View Counts from YouTube Analytics API
YouTube Analytics API provides accurate historical view counts for the first 24 hours after upload.
Why Analytics API?
| Method | Accuracy | Data Availability |
|---|---|---|
| Current view count | Approximate | Real-time |
| Analytics API query | Exact | 24-48 hour delay |
The Analytics API returns exact views during the 24-hour window, even if you check days or weeks later.
Prerequisites
Required OAuth scope:
https://www.googleapis.com/auth/yt-analytics.readonly
Setup
import { google } from 'googleapis';
class YouTubeClient {
private youtubeAnalytics: any;
constructor(private authManager: AuthManager) {
const oauth2Client = authManager.getOAuth2Client();
this.youtubeAnalytics = google.youtubeAnalytics({
version: 'v2',
auth: oauth2Client,
});
}
}
Fetch 24-Hour Views
async function fetch24HourViews(
videoId: string,
uploadedAt: string // ISO 8601 timestamp
): Promise<number | null> {
await this.authManager.getAccessToken();
try {
// Calculate 24-hour window
const uploadTime = new Date(uploadedAt);
const endTime = new Date(uploadTime.getTime() + 24 * 60 * 60 * 1000);
// Format dates as YYYY-MM-DD for Analytics API
const startDate = uploadTime.toISOString().split('T')[0];
const endDate = endTime.toISOString().split('T')[0];
// Query Analytics API
const response = await this.youtubeAnalytics.reports.query({
ids: 'channel==MINE', // Authenticated user's channel
startDate,
endDate,
metrics: 'views',
dimensions: 'video',
filters: `video==${videoId}`,
maxResults: 1,
});
// Extract view count
if (response.data.rows && response.data.rows.length > 0) {
const viewCount = response.data.rows[0][1];
return typeof viewCount === 'number' ? viewCount : parseInt(viewCount, 10);
}
return null; // Data not available
} catch (error: any) {
this.handleAnalyticsError(error, videoId);
return null;
}
}
Date Window Calculation
// Example: Uploaded at 2026-01-05 10:00:00 UTC
const uploadTime = new Date('2026-01-05T10:00:00.000Z');
const endTime = new Date(uploadTime.getTime() + 24 * 60 * 60 * 1000);
const startDate = '2026-01-05'; // Upload date
const endDate = '2026-01-06'; // Upload date + 24 hours
// Query returns views between 2026-01-05 10:00:00 and 2026-01-06 10:00:00
Error Handling
function handleAnalyticsError(error: any, videoId: string): void {
if (error.code === 403) {
console.warn(
`Analytics API access denied for video ${videoId}. ` +
'Ensure yt-analytics.readonly scope is granted.'
);
} else if (error.code === 400) {
console.warn(
`Invalid date range for video ${videoId}. ` +
'Analytics data requires 24-48 hours to become available.'
);
} else {
console.error(`Failed to fetch 24hr views: ${error.message}`);
}
}
Common Errors
| Error Code | Meaning | Solution |
|---|---|---|
| 403 | Insufficient permissions | Grant yt-analytics.readonly scope |
| 400 | Invalid date range | Wait 24-48 hours after upload |
| 404 | Video not found | Verify video ID |
Data Latency
Analytics data requires 24-48 hours to become available:
// Check if enough time has passed
function isAnalyticsDataAvailable(uploadedAt: string): boolean {
const uploadTime = new Date(uploadedAt);
const now = new Date();
const hoursSinceUpload = (now.getTime() - uploadTime.getTime()) / (1000 * 60 * 60);
return hoursSinceUpload >= 48; // 48 hour buffer
}
Fallback Strategy
If Analytics API fails, fall back to current view count:
async function fetch24HourViewsWithFallback(
videoId: string,
uploadedAt: string
): Promise<{ source: string; views: number }> {
// Try Analytics API first
const analyticsViews = await this.fetch24HourViews(videoId, uploadedAt);
if (analyticsViews !== null) {
return { source: 'analytics', views: analyticsViews };
}
// Fallback: current view count
const currentViews = await this.fetchCurrentViews(videoId);
return { source: 'current', views: currentViews };
}
Usage Example
const uploadedAt = '2026-01-05T10:00:00.000Z';
const views = await fetch24HourViews('abc123', uploadedAt);
if (views !== null) {
console.log(`Exact 24hr views: ${views}`);
} else {
console.log('Analytics data not available yet');
}