How to create a job in the YouTube Studio ‘Reports’ section or via the API
You can create a YouTube Reporting job (which tells YouTube to generate daily bulk data reports for you) either through the API or, for certain system-managed reports, they might be automatically available via the Studio interface.1
Method 1: Via the YouTube Studio ‘Reports’ Section
Currently, you cannot manually create new custom Reporting API jobs directly within the standard YouTube Studio interface. The Studio interface focuses on the Analytics API (visual dashboards, customizable charts, exporting the current view) rather than scheduling bulk CSV downloads via the Reporting API.
However, if you are a Content Owner (usually managing multiple channels or dealing with Content ID), YouTube automatically generates certain “System-Managed Reports” for you.2 These cover things like ad revenue and asset performance.3
To access and download these pre-generated System-Managed Reports:
- Sign in to YouTube Studio.
- Make sure you are viewing as the Content Owner (you might need to switch accounts using your profile picture in the top right).
- From the left menu, select Reports. 📄
- At the top of the page, select the type of report you want (e.g., Financial Summary, Asset Performance).
- Choose the frequency (Weekly or Monthly) and the version of the report.
- Click the report name for the desired date range to download the CSV file.
Method 2: Via the YouTube Reporting API (Using Python)
This is the standard way to create custom reporting jobs for various data types (like daily video views, demographics, traffic sources, etc.).
Prerequisites:
- Python installed.4
- Google API Client Library for Python installed:Bash
pip install google-api-python-client google-auth-oauthlib google-auth client_secrets.jsonfile downloaded from your Google Cloud project (with YouTube Reporting API enabled).- OAuth 2.0 authentication handled (the script below includes this).
Python Code (create_job.py):
Python
import os
import pickle
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
from google.auth.transport.requests import Request
# --- CONFIGURATION ---
# Need read/write scope to create jobs
SCOPES = ['https://www.googleapis.com/auth/yt-analytics.readonly']
API_SERVICE_NAME = 'youtubereporting'
API_VERSION = 'v1'
CLIENT_SECRETS_FILE = 'client_secrets.json'
TOKEN_PICKLE_FILE = 'token.pickle' # Same file as the download script
# --- AUTHENTICATION ---
def get_authenticated_service():
"""Handles OAuth 2.0 flow and returns an authenticated API service."""
creds = None
if os.path.exists(TOKEN_PICKLE_FILE):
with open(TOKEN_PICKLE_FILE, 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
try:
creds.refresh(Request())
except Exception as e:
print(f"Error refreshing token: {e}. Re-authenticating.")
creds = None # Force re-authentication if refresh fails
if not creds: # Need to authenticate
if not os.path.exists(CLIENT_SECRETS_FILE):
print(f"Error: {CLIENT_SECRETS_FILE} not found.")
exit()
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRETS_FILE, SCOPES)
creds = flow.run_local_server(port=0)
with open(TOKEN_PICKLE_FILE, 'wb') as token:
pickle.dump(creds, token)
return googleapiclient.discovery.build(
API_SERVICE_NAME, API_VERSION, credentials=creds)
# --- List Available Report Types ---
def list_report_types(service):
"""Lists available report types."""
print("Fetching available report types...")
try:
results = service.reportTypes().list().execute()
report_types = results.get('reportTypes', [])
if not report_types:
print("No report types found.")
return None
else:
print("Available Report Types:")
for i, r_type in enumerate(report_types):
print(f" [{i+1}] ID: {r_type['id']}")
print(f" Name: {r_type['name']}")
return report_types
except googleapiclient.errors.HttpError as e:
print(f"An API error occurred: {e}")
return None
# --- Create Job Function ---
def create_reporting_job(service, report_type_id, job_name):
"""Creates a new reporting job."""
print(f"\nCreating job '{job_name}' for report type '{report_type_id}'...")
job_body = {
'reportTypeId': report_type_id,
'name': job_name
}
try:
response = service.jobs().create(body=job_body).execute()
print("\n--- Job Created Successfully ---")
print(f"Job ID: {response['id']}")
print(f"Job Name: {response['name']}")
print(f"Report Type ID: {response['reportTypeId']}")
print(f"Create Time: {response['createTime']}")
print("--------------------------------")
print("Reports will start generating within 48 hours.")
return response
except googleapiclient.errors.HttpError as e:
print(f"An API error occurred: {e}")
error_details = e.resp.get('content', b'').decode('utf-8')
if "jobs.create" in str(e) and "409" in str(e): # 409 Conflict means it likely already exists
print("Error: A job with this reportTypeId might already exist for your channel.")
elif "403" in str(e) and "system-managed" in error_details.lower():
print("Error: Cannot create jobs for system-managed report types.")
else:
print(f"Details: {error_details}")
return None
# --- MAIN EXECUTION ---
def main():
service = get_authenticated_service()
available_types = list_report_types(service)
if not available_types:
return
# --- User Input ---
while True:
try:
choice = int(input(f"Enter the number of the report type you want to create a job for (1-{len(available_types)}): "))
if 1 <= choice <= len(available_types):
selected_report_type = available_types[choice-1]
break
else:
print("Invalid choice.")
except ValueError:
print("Please enter a number.")
job_name_input = input(f"Enter a name for this job (e.g., 'Daily {selected_report_type['name']}'): ")
if not job_name_input:
job_name_input = f"My {selected_report_type['name']} Job" # Default name
# --- Create the Job ---
create_reporting_job(service, selected_report_type['id'], job_name_input)
if __name__ == '__main__':
main()
How to Use the API Script:
- Save the code as
create_job.py.5 - Make sure
client_secrets.jsonis in the same folder. - Run it:
python create_job.py - It will first authenticate (if needed).
- Then, it lists the available report types you can create jobs for (e.g.,
channel_basic_a2,channel_traffic_source_a2, etc.). - It prompts you to enter the number corresponding to the report type you want.
- It prompts you to enter a name for the job.
- It calls the
jobs.createmethod and confirms if the job was created successfully.6
Once created, YouTube will start generating daily CSV reports for that job, which you can then download using the other script (from the previous answer). Remember, it takes up to 48 hours for the first report to appear.7
