Paginating Results

REST API methods that might return a large number of individual elements support pagination. Some examples of these methods include Query Datasources and Get Users in Site. When you call these methods, the response includes a <pagination> element that has pageNumber, pageSize, and totalAvailable attributes whose values you can use to implement paging.

The following example shows what the response body might look like for a Get Users in Site request where there are a total of 158 users in the site:

<?xml version="1.0"?>
<tsResponse>
  <pagination pageNumber="1" pageSize="100" totalAvailable="158"/>
  <users>
    <user id="abf3a02d-d559-4e5e-a3e7-4ca0188a5b3b" name="Ashley"
          siteRole="None" lastLogin="" externalAuthUserId=""/>
    <user id="892be621-66a6-42ef-9c65-99e5cb18afeb" name="Michelle"
           siteRole="PublisherInteractor"  lastlogin=" " externalAuthUserId=""/>
    <user id="688b1c97-4a11-4b14-b9a5-b13f10909549" name="Alan"
          siteRole="Publisher" lastLogin="" externalAuthUserId=""/>
    <user id="486d3023-b266-4fe6-a0f1-9cd5ea215972" name="Susan"
          siteRole="Viewer" lastLogin="" externalAuthUserId=""/>
    <user id="bc272be1-7c60-41c1-ad24-b01266d1ff2e" name="Laura"
          siteRole="Interactor" lastLogin="" externalAuthUserId=""/>
    <user id="efdd25a6-c83a-42a0-8095-987ba8419c95" name="Andrew"
          siteRole="PublisherInteractor" lastLogin="" externalAuthUserId=""/>
    <user id="6dfc3778-2972-49ba-994f-215d08578ff4" name="Adam"
          siteRole="Interactor" lastLogin="" externalAuthUserId=""/>
    <user id="f642ac44-43ca-45b6-95ba-c8ca70fb3ee7" name="Henry"
          siteRole="PublisherInteractor" lastLogin="" externalAuthUserId=""/>
    <user id="65ee1a5a-72ca-408f-9aa2-b8cc7797e3d1" name="Fred"
          siteRole="Viewer" lastLogin="" externalAuthUserId=""/>
    <user id="3354bcac-f935-4b5d-a898-477c551334c8" name="Jane"
           siteRole="PublisherInteractor" lastLogin="" externalAuthUserId=""/>
    ... Another 90 <user> elements here ...
  </users>
</tsResponse>

If a method supports pagination, you can pass two parameters as part of the request: the page size (that is, the number of elements to return per call) and the page number. The default page size for an individual call is 100, but you can specify a page size that’s any positive integer. The page number is a 1-based (not zero-based) value. The default page number is 1, meaning that if you do not include a page number, Tableau Server returns the first page of elements.

You pass page number and page size parameters using the query string on the URI, as in this example:

http://myserver/api/3.12/sites/site-id/users?pageSize=20&pageNumber=2

The page number is multiplied by the current page size to determine which elements to return. For example, if the page size is 20 and the page number is 2, the call returns items 21 through 40 of all available elements.

To use pagination, you typically perform a series of requests in a loop. Each iteration of the loop gets another page of elements until you have received all available elements.

How Elements are Ordered

To maintain consistency, if no explicit sort order is specified (see Filtering and Sorting in the Tableau REST API) the elements returned are indexed and sorted internally. For example, if a method returns 158 elements, those items will be sorted and listed in the same order in subsequent method calls. The sorting is done on an internal index, and not on the locally unique identifier (LUID) for the resource (for example, not on the user id).

Note that the REST methods are not synchronized, so if another method removes an item from the list, between paging calls, it is possible that some items might be missed if they fall on a page boundary. The effect is temporary, as no data is lost, and further requests sort and index the elements correctly.

Python Example for Paging

The following example in Python shows how to use paging to get a list of users on the site. Note the following about this example:

  • The example is not complete. It assumes that you previously called the Sign In method and got back an authentication token that you've stored the token in the variable named token. It also assumes that you got back the site ID and have stored it in the variable named site_id. For more information, see Signing In and Signing Out (Authentication).

  • The code makes HTTP requests using the Request library that's built into Python.

  • The code parses the XML block in the response body using the xml.etree.ElementTree method that's built into Python. For details, see the ElementTree XML API(Link opens in a new window) documentation on the Python website.

try:
    # Python 3
    from urllib.request import urlopen, request
except:
    # Python 2
    from urllib2 import urlopen, Request
import xml.etree.ElementTree as ET # For parsing XML responses

# ... Code here to sign in ...

# Note: A Sign In request has already been made and the authentication token is
# in the variable named "token"
headers = {'X-tableau-auth': token}

page_size = 50
page_number = 1  # 1-based, not zero based
total_returned = 0
done = False
user_name_list = []

while not(done):
    request_url = 'http://{server}/api/3.12/sites/{site_id}/users'.format(
        server=server, site_id=site_id)
    paging_parameters = '?pageSize={page_size}&pageNumber={page_number}'.format(
        page_size=page_size, page_number=page_number)
    full_url = request_url + paging_parameters
    print(full_url)

    # Make request
    req = Request(full_url, headers=headers)
    req = urlopen(req)
    server_response = req.read().decode("utf8")

    response_xml = ET.fromstring(server_response)

    # Get total number of records from the <pagination> element
    total_available = response_xml.find('.//t:pagination',
        namespaces={'t': "http://tableau.com/api"}).attrib['totalAvailable']
    # Note! Need to convert "total_available" to integer
    total_available = int(total_available)

    page_number += 1
    total_returned += page_size

    # Get user details from <users> element
    user_element = response_xml.findall('.//t:user',
        namespaces={'t': "http://tableau.com/api"})

    # Display individual user names
    for user in user_element:
        print (user.attrib['name'])

    if(total_returned >= total_available):
        done = True

# ... Code here to sign out ...


Thanks for your feedback!