Using the Looker API to generate PDFs

  • Looker Staff
  • 10 replies

Update: This article is now out of date. For the latest info on how to render and download a dashboard’s PDF using the Looker API, please see our Looker SDK Examples repo on Github.

Downloading a PDF version of your dashboard is great and is very easy to do via the Looker UI. In this article, we make use of the Looker API (and the python SDK client) to do this.

Step 1:

Authenticate into the Looker API.

import looker

base_url = ''

client_id = ''

client_secret = ''

# instantiate Auth API

unauthenticated_client = looker.ApiClient(base_url)

unauthenticated_authApi = looker.ApiAuthApi(unauthenticated=_client)

# authenticate client

token = unauthenticated_authApi.login(client_id=client_id, client_secret=client_secret)

client = looker.ApiClient(base_url, 'Authorization', 'token ' + token.access_token)

Step 2:

Create a new task to render the desired dashboard to a PDF using the create_dashboard_render_task endpoint. Please take note of the format of the dashboard_filters, which is a string and expects the filters in query URL format. e.g.: "My Filter=New York&My Other Filter=Brooklyn".

# instantiate render task API

renderTask = looker.RenderTaskApi(api_client=client)

height = 842

width = 595

output_format = 'pdf'

dashboard_id = 241

body = {

"dashboard_style": "tiled",

"dashboard_filters": {

"Created Date=12 months ago for 12 months"



# fire a render task and get its ID

task_response = renderTask.create_dashboard_render_task(dashboard_id, output_format, body, width, height)

task_id =

###Step 3:

Use the render_task(id) endpoint to confirm the the render task has finished. Consequently, we can get the produced document using the render_task_results endpoint as follows:

# get the produced results

results = renderTask.render_task_results(task_id, _preload_content = False)

data =

# write it to PDF

with open('output.pdf', 'wb+') as f:


PS: the _preload_content = false parameter is used to tell Python not to parse the body of the response as text.

12 replies

I am not able to locate any Looker Python SDK which has a valid reference to looker.ApiClient.

Can you pass on the location where to download this this Looker Python SDK?


Perhaps I misunderstood. Looks like this should be generated based off this article

I’m not all that familiar with swagger, but it’s confusing to me why this client would have to be generated. Especially considering all the dependencies required in order to get it done.

For now I’m going to attempt to interact with the API directly via http, instead.

Userlevel 2

Hi evan,

As you surmised, we don’t currently have a ready-made Python client SDK package to access the Looker API available for download. You can generate a Python client SDK from the Looker API swagger metadata, as covered in the article you linked.

This does introduce some additional steps that you, our customers, have to go through to get started using the Looker API, and for that I apologize. The swagger codegen step does allow a wide variety of programming languages to access the Looker REST API without any additional effort from us.

Some folks who are comfortable making HTTP REST requests skip the whole SDK step and just write their code to make HTTP requests to the Looker API URLs directly. The downside to that is you don’t get the data types built for you, and you have to think in terms of HTTP requests all the time. The Swagger generated client-SDKs for the Looker API offer the convenience of accessing the Looker API like a function call library so you don’t have to get down and dirty with HTTP.

Providing pre-packaged Looker client SDK downloads is high on my personal wish list, but until I can find a couple of free weekends I’m not likely to make much progress on this front. 😒

If/when we do offer pre-packaged client SDKs for the Looker API, it will definitely be announced in an article here on this forum. Watch this space! 😉



Can this be done with the Ruby SDK?

Userlevel 2

@mikeghen1 Yes, the Looker client SDK for Ruby can download PDFs.


Thanks, I found the gem already.

I don’t see any documentation on how to use the SDK to do that. Is there documentation for how to use that gem to do things other than manage users?

Userlevel 2

Hi @mikeghen1,

Here is our API doc on how to create a render task for a dashboard. But, I have played with this before and here is an example where I create a .png file for a look

#!/usr/bin/env ruby

require 'looker-sdk'

sdk =

:client_id => ENV['API_ID'],

:client_secret => ENV['API_KEY'],

:api_endpoint => "",

:connection_options => {:ssl => {:verify => false}}


png = sdk.create_look_render_task(164, "png", {}, {:query => {:width => 1000, :height => 1000}})

id = png[:id]

until sdk.render_task(id)[:status] == 'success' do


results = sdk.render_task_results(id)'look.png', 'w') { |file| file.write(results) }

As you can see, we first have to create a render task. Then, we have to wait until that task is completed which is what we do here:

until sdk.render_task(id)[:status] == 'success' do


Then, once it returns true, we get the results, store it in a variable, and save it to a file. Let me know if this helps! And of course, you will have to make some changes to your ruby script.



Thanks Vincent!

I followed the instructions to generate the PDF with Python and got this error:

Traceback (most recent call last):

File "", line 38, in <module>

results = renderTask.render_task_results(task_id, _preload_content=False)

File "/Users/mikeghen/Documents/REDACTED/", line 561, in render_task_results

" to method render_task_results" % key

TypeError: Got an unexpected keyword argument '_preload_content' to method render_task_results

I generated my Python looker package using the instructions provided here: Generating Client SDKs for the Looker API. (Doing that was a pain 😩 I don’t understand why Looker only provides a Ruby SDK) I confirmed it worked with a few other API calls before I tried to do this PDF, render task thing.

When I just remove _preload_content I get:

Traceback (most recent call last):

File "", line 46, in <module>

data =

AttributeError: 'str' object has no attribute 'data'

Looks like if I just pass results rather than this works out OK without _preload_content:

results = renderTask.render_task_results(task_id)

# write it to PDF

with open('output.pdf', 'wb+') as f:

Userlevel 1

I also got an error when trying to supply a _preload_content argument to render_task_results.

In order to get PDF downloads working using the Swagger-generated Python SDK, I had to do the following:

Using Python 3.x you’ll see these line in the Swagger-generated file:

168         # In the python 3, the is bytes.                                                             

169 # we need to decode it to string.

170 if sys.version_info > (3,):

171 ='utf8')

You’ll need to do something about that when downloading the PDF results, or else your API client will try to convert it to text.

My solution was to add a decode parameter to the RESTClientObject.request method, setting the default value to True, so now the decode condition looks like this:

  153         # In the python 3, the is bytes.                                                           

154 # we need to decode it to string.

155 if sys.version_info > (3,) and decode:

156 ='utf8')

I made similar updates to the wrapped calls to the REST client in

You need to make sure that you bypass deserialization of the data in the __call_api method in

  146         # deserialize response data                                                                              

147 if decode:

148 if response_type:

149 deserialized_data = self.deserialize(response_data, response_type)

150 else:

151 deserialized_data = None

152 else:

153 deserialized_data =

Finally in apis/, you can update the api call like this:

  609         response = self.api_client.call_api(resource_path, 'GET',                                                

610 path_params,

611 query_params,

612 header_params,

613 body=body_params,

614 post_params=form_params,

615 files=local_var_files,

616 response_type='str',

617 auth_settings=auth_settings,

618 decode=False,

619 callback=params.get('callback'))

Here’s a gist that includes the affected files:

Userlevel 4

Note: if width and height parameters there are wrong, the PDF may render super funky

Are we going to support Expand Tables as part of API , That is a great option to have if we are generating large number of PDF’s.

If we fetch PNG from look, how will look gets refreshed automatically without opening it ?


I want to generate PNG every 2 hours