Welcome to the DataDev Quest Challenge for January 2025! This challenge is designed to learn how to use Tableau REST API, Tableau Server Client, and Tableau Developer Sandbox to generate a PDF from a Workbook published in Tableau Cloud.
Challenge Overview
Objective:
Write a Python Script that uses Download Workbook PDF (REST API) to generate a PDF from Tableau Cloud. Check the challenge at the end of the guide.
Why this challenge?
Many organizations rely on Tableau to generate PDF reports to share critical insights. However, when dealing with a large number of workbooks, manually generating these reports becomes time-consuming and error-prone. Automating this process using Tableau Server Client and REST API not only saves time but also ensures consistency and scalability.
Many of these Reports also require that you dynamically change the selection and pre-select the data to print it.
Learning Goals
- Get your Tableau Developer Sandbox
- Configure Personal Access Token (PAT)
- Install Tableau Server Client
- Connect to your Developer Site using PAT
- Search a Workbook by Name and Content URL
- Generate PDF from Workbook
- Learn how to pass parameters and filters to create statics PDFs.
Submission Guidelines
- Source Code: Publish your project publically in the GitHub profile
- Add README: Include setup instructions and describe how to run the program.
- Video of Solution: Include a video of your solution in the README file, which you can publish on YouTube and embed the iframe. Or save the video file in the directory root inside the repository.
- Comments: Ensure your code is well-commented.
- Submission: Submit your challenge in the following **forms**
Additional Resources
- Let’s Play A Game by Kyle Massey
- How to get your Tableau Online Sandbox?
- How to get a Tableau PAT (Personal Access Token)?
- Personal Access Token (PAT)
- Enable Personal Access Token (PAT)
- REST API
- Tableau Server Client (Python)
- Install TSC
- Filter and Sort
- Workbooks
- Workbook Item
- Views
- Views Item
- views.populate_pdf
- Download View as PDF
- PDFRequestOptions
- workbooks.populate_pdf
- Download Workbook PDF
- Automate Tableau Data Sources refresh using Python
- Automate getting Tableau Server Users with REST API and Python
- DataDev Slack Channel
Getting Started
The first step is to get and set up your Tableau Developer Sandbox. By following my Medium Post, you will get a step-by-step guide to configuring it.
1. In your Tableau Cloud Site, create a Folder with the name DataDevQuest and a subfolder 202501 as follows:

2. Download Let’s Play A Game by Kyle Massey to your machine.
3. Open with Tableau Desktop and Sign In to your site using your full URL, copying and pasting from your browser. The URL will look similar to https://10ax.online.tableau.com/#/site/cristiansaavedradx
If It asks you to enter the URI, copy the text after site/ in the URL, in my example, it is cristiansaavedradx


4. Publish the workbook selecting the location DataDevQuest / 202501 and All Sheets and not show sheets as tabs:

5. Be sure that you have Enabled the Personal Access Token (PAT) and configure your Personal Access Token (PAT). If you need help, follow my Medium Post, where I explain how to get it.
6. Install Tableau Server Client (TSC) in your Python environment. You can check Medium Post for more information.
7. Modify the following example code with your URL, PAT Token, PAT Secret, and Site ID.
import tableauserverclient as TSC
my_server_url = 'https://10ax.online.tableau.com/'
my_token_name = 'test'
my_token_secret = '+z+Gy5CSSi+VVotuzo44A==:ai5xKL1A6Dfmf6OIstMuiOGhGbvN0MxpS'
my_site_id = 'cristiansaavedradx'
tableau_auth = TSC.PersonalAccessTokenAuth( token_name=my_token_name
,personal_access_token=my_token_secret
,site_id=my_site_id)
server = TSC.Server(my_server_url, use_server_version=True)
with server.auth.sign_in_with_personal_access_token(tableau_auth):
print('[Logged in successfully to {}]'.format(my_server_url))
8. Execute the code, and you will get a Logged in successfully message to your Tableau Cloud Site.
9. Modify the following example code that searches the Kyle Massey Dashboard in your Tableau Cloud Developer Site using the Name and passing RequestOptions. For more information, check Filter and Sort
import tableauserverclient as TSC
my_server_url = 'https://10ax.online.tableau.com/'
my_token_name = 'test'
my_token_secret = '+z+Gy5CSSi+VVotuzo44A==:ai5xKL1A6Dfmf6OIstMuiOGhGbvN0MxpS'
my_site_id = 'cristiansaavedradx'
my_workbook = "Let's Play A Game"
tableau_auth = TSC.PersonalAccessTokenAuth( token_name=my_token_name
,personal_access_token=my_token_secret
,site_id=my_site_id)
server = TSC.Server(my_server_url, use_server_version=True)
with server.auth.sign_in_with_personal_access_token(tableau_auth):
print('[Logged in successfully to {}]'.format(my_server_url))
req_option = TSC.RequestOptions()
req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name
,TSC.RequestOptions.Operator.Equals
,my_workbook))
workbooks, pagination_item = server.workbooks.get(req_options=req_option)
if workbooks:
print(f"=== Workbook ===")
print(f"Name:{workbooks[0].name}")
print(f"luid:{workbooks[0].id}")
print(f"URL:{workbooks[0].webpage_url}")
print(f"Content URL:{workbooks[0].content_url}")
10. Execute the code, and you will get information like the name, luid, URL, and Content URL. The Content URL is a unique resource that you will see also in the URL when you use the Tableau Web Interface, for example:
https://10ax.online.tableau.com/#/site/cristiansaavedradx/views/LetsPlayAGame/LetsPlayAGame?:iid=1
11. Modify the following code example to use your PAT and replace the variable pdf_file_name with the path where you want to download the pdf on your machine.
import tableauserverclient as TSC
import os
my_server_url = 'https://10ax.online.tableau.com/'
my_token_name = 'test'
my_token_secret = '+z+Gy5CSSi+VVotuzo44A==:ai5xKL1A6Dfmf6OIstMuiOGhGbvN0MxpS'
my_site_id = 'cristiansaavedradx'
my_content_url = 'LetsPlayAGame'
pdf_file_name = f'./02_intermediate/{my_content_url}.pdf'
tableau_auth = TSC.PersonalAccessTokenAuth( token_name=my_token_name
,personal_access_token=my_token_secret
,site_id=my_site_id)
server = TSC.Server(my_server_url, use_server_version=True)
with server.auth.sign_in_with_personal_access_token(tableau_auth):
print('[Logged in successfully to {}]'.format(my_server_url))
req_option = TSC.RequestOptions()
req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.ContentUrl
,TSC.RequestOptions.Operator.Equals
,my_content_url))
workbooks, pagination_item = server.workbooks.get(req_options=req_option)
if workbooks:
wb = workbooks[0]
print(f"=== Workbook ===")
print(f"Name:{wb.name}")
print(f"luid:{wb.id}")
print(f"URL:{wb.webpage_url}")
print(f"View:{wb.content_url}")
pdf_options = TSC.PDFRequestOptions(page_type='unspecified', orientation='landscape')
server.workbooks.populate_pdf(wb, pdf_options)
print(f'Path:{os.getcwd()}')
with open(pdf_file_name, 'wb') as f:
f.write(wb.pdf)
print('[PDF Generated]')
