Python: Dynamic Power BI PDFs with the REST API
Export individualized Power BI reports to hundreds of recipients — no per-user licenses, no manual subscriptions — with a Python script on the Power BI REST API.
TL;DR
- When you need to send static reports to many people who may not have Power BI licenses, per-user subscriptions and premium seats get expensive and unmanageable fast. A Python script on the Power BI REST API's export-to-file endpoint solves it: it filters one report per recipient, exports each as a PDF, emails it, and runs unattended on a schedule — so report-only consumers never need their own license.
- The approach needs a Fabric or capacity license (Premium Per User will not work for export-to-file) and an Azure Entra app registration for authentication.
- Full source — Python, PowerShell, and config — is on GitHub.
Table of Contents
Introduction
Sometimes you have a requirement to export large volumes of static reports to users who may or may not have Power BI licenses. One way to accomplish this is through email subscriptions. The issue is that a large population — say, 50+ users — would each need their own subscription managed per report. No good (50 users across 10 reports is a nightmare to manage).
Another non-optimal option is to provision per-user licenses, but this can be tricky for the mid-size company. 100 users at $12/month can be costly for single-report consumption (roughly $14k+ annually). Double that if you use paginated reporting.
We will review a solution where a report is iteratively filtered by "employee" and sent automatically to a manager, where notes can be added, and the final write-up is forwarded to the intended audience.
Note: the GitHub repo with all code is here — GitHub: Python Dynamic Power BI PDFs with REST API.
Prerequisites
Programming Tools
- Python
- PowerShell
- VS Code (highly recommended)
Environment Settings
Microsoft license requirements:
- You will need a minimum Fabric Trial license. Ultimately this will cost ~$250/month once the trial ends after 60 days. PPU will NOT work.
- Microsoft Doc
Microsoft Fabric admin settings:
- "Export reports as PowerPoint presentations or PDF documents" — enabled by default; search for "PowerPoint" in your admin settings.
- "Export reports as image files" — required only for .png and disabled by default; search for "image" in your PBI admin settings.
- Microsoft Doc
Azure Entra Application
To use the Power BI REST API, an Azure Entra application is required. This application lets you authenticate and authorize access to the Power BI service. It is generally free with a Microsoft subscription and easy to set up.
Steps to set up an Azure Entra application:
- Register an Azure Entra application:
- Go to the Azure portal.
- Navigate to "Azure Active Directory" > "App registrations".
- Click "New registration".
- Fill in the required details (Name, Supported account types) and register the application.
- Note the Application (client) ID and Directory (tenant) ID.
- Add API permissions:
- In the registered application, go to "API permissions".
- Click "Add a permission" > "APIs my organization uses" > search for "Power BI Service".
- Add the following permissions:
Dataset.ReadWrite.AllandReport.ReadWrite.All. - Click "Grant admin consent" to grant the permissions.
- Add a client secret:
- Go to "Certificates & secrets".
- Click "New client secret" and create a secret.
- Note the client secret value — you will need it for authentication.
Note the following for the script: Display Name, Application (client) ID, Object ID, Directory (tenant) ID.
Add users:
- Go to Entra ID > Enterprise Applications > (select the application).
- Go to Users and Groups > Add User/Group (add the user or service accounts).
SMTP Settings
Setting up an SMTP server is slightly outside my scope; a quality tech can provision this quickly. However, important settings will need to be adjusted so your script works.
SMTP server — you will need: Server Address, Port, User Name, Password. Best practice is to use a service account.
Enable SMTP client authentication:
- Sign in to the Microsoft 365 admin center.
- Go to Settings > Org settings.
- Under Services, select Modern authentication.
- Ensure that "Allow Basic authentication" is enabled for the SMTP protocol (aka.ms/smtp_auth_disabled).
Add an app password to the service account:
- Log into M365 with the service account.
- Click the profile picture (top right) and select "My Account".
- In the left-hand navigation, click "Security info".
- Under "Security Info" click "Add Method".
- Select "App Password". (Note: we had to enable MFA to enable the app password.)
Additional Information
Familiarize yourself with these Microsoft Docs:
Process and Scripts
Required Python Packages
Run the following to get all required libraries: pip install requests adal pandas.
File Parameters
The following breaks down where each parameter is sourced.
- Azure Entra App: client_id, client_secret, tenant_id.
- Microsoft credentials: username, password — the account used to log into Power BI/Fabric. Make sure it has permissions to the workspace and data (RLS).
- Microsoft environment: workspace id, report id — a script finds this (see supporting scripts).
- SMTP environment: smtp_server, smtp_port, smtp_username, smtp_password.
- General: from_email, to_email — where to send and from whom (you can string multiple emails here).
- save_locally: true or false — saves files to an auto-generated "PDF Reports" folder.
For the PowerShell launcher (PS_Start_Automation): $scriptDirectory is the directory of the Python script; $pythonExecutable is the location of your Python installation; $scriptPath is the name of your Python file.
For AutomatedReports, the only required parameters are your filters. I used an "employees" table to loop through the list, and the filter expression targets a column in the semantic model (Employee[Employee Last First Name]). Update this based on your model, maintaining the correct syntax per Filter a report using query string parameters in the URL.
Main Scripts
There are three main scripts:
- PBIconfig.json — the config file holding your sensitive information (GitHub).
- PS_Start_Automation.ps1 — the PowerShell script that executes your Python script, launched by Task Scheduler (GitHub).
- AutomatedReports.py — the Python script that does the heavy lifting: connecting to the report via the app, looping and filtering, and sending the emails (GitHub).
Housed in a shared folder and working in tandem, the scripts connect automatically. If save_locally is true, a "PDF_Reports" folder is created and the generated PDFs are saved there. Full code: GitHub, Main Scripts.
Supporting Scripts
A Jupyter notebook is included so users can walk through testing scripts and establishing their environments:
- Connect to a Workspace — tests whether a user has set their environment correctly.
- Get Environment Information — exports a table of WorkspaceName, WorkspaceID, ReportName, ReportID.
- Download a Single Report — a quick test to validate you are connecting to and downloading a PDF.
- Test SMTP Configuration — tests your SMTP configuration with a summary or detailed log.
- Loop Reports and Send Email — the same logic found in AutomatedReports.py, exposed for testing.
Full code: GitHub, Supporting Scripts.
Scheduling with Task Scheduler
Task Scheduler kicks off the PowerShell job at set intervals:
- Open Task Scheduler and click "Create Task…".
- In the General tab, name the task and configure it to run with the highest privileges if needed.
- In the Triggers tab, create a new trigger: set "Begin the task" to "On a schedule", choose a frequency (e.g., daily) and start time (e.g., 2:00 AM), and click OK.
- In the Actions tab, create a new action: set "Action" to "Start a program", enter
powershell.exein the Program/script field, and in "Add arguments" enter the path to your PowerShell script (e.g.,-File "C:\Scripts\MyPythonScript\run_python_script.ps1"). Click OK. - Adjust any settings in the Conditions and Settings tabs, then click OK to create the task.
Conclusion
This guides you through implementing your own automated Power BI PDF download and distribution deployment. This version sends all reports to a single user so they can forward the reports with notes; a future version could route scripts to the appropriate recipients directly.
Again, the GitHub repo with all code is here: GitHub: Python Dynamic Power BI PDFs with REST API.
Frequently Asked Questions
How do you distribute Power BI reports to users without giving everyone a license?
Use the Power BI REST API's export-to-file endpoint from a Python script. The script filters one report per recipient, exports each as a PDF, and emails it — so report-only consumers never need their own premium license, which avoids paying roughly $12 per user per month.
What license is required to export Power BI reports to PDF via the API?
At minimum a Fabric trial or capacity license — Premium Per User will not work for export-to-file. The tenant's admin settings must also allow exporting reports as PowerPoint or PDF, and as image files if you need PNG output.
How do you schedule the automated PDF distribution?
Windows Task Scheduler launches a PowerShell wrapper that runs the Python script on a set interval. The script reads a JSON config for credentials, workspace and report IDs, SMTP settings, and the filter list, then loops through recipients unattended.
When licensing bloat is the real problem
This is the same automation that engineered $26K/year in licensing out of a client's reporting stack. If tool and license bloat is quietly eating your budget, let's talk about what's worth automating.
About the author — William Rodriguez is the founder of Analytical Ants, the delivery arm of Analytical Solutions. He spent roughly a decade architecting enterprise BI and data platforms for operations running $10M–$60B in revenue, and holds an MBA from Emory University's Goizueta Business School with dual undergraduate degrees in Finance and Managerial Science. More about Analytical Ants.