Obtaining a list of Admin Users with their Roles

Community Champion

On September 16, 2017, Canvas added an Admin CSV option to the Provisioning Report. It provides most of the information here and is built-into Canvas rather than being an external solution. It does require that you combine information from multiple tables to get human-friendly information for some of the values, so some people may still find this document useful. I've added a Method 0 to the document to include Canvas' report.

One request that has surfaced multiple times in the Community is how to quickly get a list of admin users and the roles those users have. On March 3, 2017,  @liuz21  asked it in Is there a quick way to get the user list for each admin role?. There,  @abunag  provided the standard answer of "I manually maintain this list" and that he did it for over 200 sub-accounts. Our institution is small and we know who our admins are, so I didn't realize the problem was that large. Anthony's solution is typical of what admins are forced to do, but neither encouraging nor a good use of his time. Obtaining the list automatically via a script sounded like something that could be done without too much hassle. My original mental estimate of an hour turned into a weekend and then that turned into about five days. The moral of the story is that you should never use the words "easy" when it comes to adding functionality to Canvas.

There's another moral to the story. After spending several days writing the script to do this, completing the documentation, and getting ready to publish the tool, I went looking for places in the Community that mentioned it and found that I had already written a Google Sheet script to do this back in December 2015. It showed me that I really need to do a better job of organizing my scripts because I'm forgetting which ones I've already written. It also points out the problem of finding things in the Community -- items buried within a question or feature request are harder for people to find than a document. Sometimes, even the person who wrote it forgets that he wrote something. But it also may have been why I thought this wouldn't be too bad in the first place -- I had already done it once.

Method 0: Use the Admin CSV option from the Provisioning Report

When I wrote this script, there was nothing built into Canvas that would provide the information. The September 16, 2017, production release of Canvas added the ability to download the Admin CSV file for an account or a sub-account. This mostly obsoleted the information that I have in this document.

The provisioning reports are designed to provide the information necessary so that you could recreate the accounts. We often take the information and reassemble it into a more useful form. This means looking up Canvas IDs from one table and tying them to a value in another table.

For example, if you want the name of the (sub)account, you have to take the canvas_account_id in the Admins CSV file and link it to the canvas_account_id in the Accounts CSV and then you can get the human-friendly name from the name field of the Accounts CSV report.

But the good news is that it's now built into Canvas! For those who want a report that brings in that extra information automatically, then the information from the original document may be helpful.

Method 1: Download link inside Canvas

This method adds a button that will generate a CSV file that you can open in Excel that will contain a list of the admin accounts and the roles that they have. By default, the CSV file contains (in this order): the account name, the user name, user role within that account, login ID, sortable name, Canvas account ID, Canvas user ID, Canvas role ID, SIS user ID, SIS login ID, SIS account ID, and Canvas parent account ID.

CSV File


Here are the quick install steps for those who don't want to read the full instructions.

  1. Install the Tampermonkey browser extension.
  2. Install the List Admin Roles user script.

How to Use

The script adds a button to the main Admin People page for your account and sub-account. These are the pages that you get to by going to Admin and choosing People or by clicking on Sub-Accounts from the Admin page and choosing People.

Location of item on menu

When you see the "List Account Admins", you click it and wait. How long you wait depends on how many sub-accounts and admin users you have.

It attempts to gather information for all sub-accounts of whichever account page you are viewing when you click the button. This means that you can get the admin list for all of your sub-accounts or you can go to a specific account and then get all of the admin users for just that sub-account.

Grouping and Sorting

The information is grouped based off the account hierarchy that you have specified. The primary sorting and grouping of the information in the report matches what you get when you click on the Sub-Accounts link from the account admin page.

It starts with the root account, where root in this case means whichever account or sub-account you were viewing when you clicked the button. All of the admins for that (sub)account are listed first and then any sub-accounts for that account come next in alphabetical order.

Within each account or sub-account, the users are listed alphabetically by the sortable name (if available) or their name. 

If an account does not have any admins in it, then it is not listed in the report. In other words, this is not a list of your sub-accounts, this is a list of users and what roles they have.

Custom URLs

If you do not use a custom URL, then you should not have to change anything to make the script work. By default, it is is setup to recognized *.instructure.com sites, including test and beta instances. However, if you are using a custom URL then you will need to modify line 5 of the code.

// @include     /^https://.*\.instructure\.com/accounts/[0-9]+$/‍‍‍‍‍‍‍‍

This is a regular expression that tells it which pages to run on. To make sure that it doesn't run on sub-pages within your admin pages, I make sure that it has just an account number at the end. This means that I need to match based on a regular expression instead of the wildcard * that other scripts use. In regular expressions, dots have special meanings, so if you want use a dot, you need to escape it with a backslash. If you want canvas.site.edu, you need to enter it as canvas\.site\.edu.

The following include line would match canvas.site.edu, canvas.test.site.edu, and canvas.beta.site.edu:

// @include     /^https://canvas(\.test|\.beta)?\.site\.edu/accounts/[0-9]+$/‍‍‍‍‍‍‍‍

Deciding what to include

By default, the report includes the account name, user name, user role, login ID, sortable name, Canvas account ID, Canvas user ID, Canvas role ID, SIS user ID, SIS login ID, SIS account ID, and Canvas parent account ID. However, all of this is configurable using the variable reportFields at the top of the code.

Here's an abbreviated section of code.

var reportFields = [ {
'name' : 'Account',
'src' : 'a.name'
}, {
'name' : 'Name',
'src' : 'u.name'
}, {
'name' : 'Role',
'src' : 'r.role'

The order that the information is listed in the CSV export is the order that they are listed in the reportFields array.

Each entry in the array is an object that contains a name and a source (src). The name is the heading that will appear in the report and the defaults have no spaces to assist with other software like R that doesn't like a space in the heading. The source for the information is made up of two parts, separated by dot. The first part is an abbreviation for the object that contains it and could be the a for account, r for role, or u for user. The part after the dot is the field that is returned via the API field.

Here is a list of the available information.

  • User: id, integration_id, login_id, name, short_name, sis_import_id, sis_login_id, sis_user_id, sortable_name
  • Role: id, role
  • Account: default_group_storage_quote_mb, default_storage_quota_mb, default_time_zone, default_user_storage_quota_mb, id, name, parent_account_id, root_account_id, workflow_state

Here are some notes on the available information.


  • The email is not available through those requests, it would need a separate API call for each user that was an admin and that could take a while.
  • For us, there's not much difference between short name and name, so I just went with name. The sortable_name is "Last, First" so it becomes sortable by last name.


  • There is actually more information available about the roles than what is provided. However, that was going to require an additional API call for each role or multiple calls to fetch all the roles for an account and then repeating that for different accounts. The List roles API had a query parameter to fetch information about roles that were created in a parent account, but not one to fetch role information for all sub-accounts, which is what would have made this really nice.


  • There's a lot of stuff regarding storage quotas here. I didn't see how that was germane to this report.
  • The parent_account_id and root_account_id could be used to establish some kind of hierarchy of sub accounts, but I figured that most people knew what their hierarchy is and indenting in the spreadsheet to reflect that isn't really a viable option.
  • The workflow_state is used as a filter on 'active', so displaying it doesn't accomplish anything.

Behind the Scenes

You do not need to understand this section to use it. This is for those who want to take it and go further with it.

When I first started this, I though there were basically three API calls that needed made. When it was finished, there were still three, although some of them were different than what I had originally thought. The process is simpler and faster, but provides less information than was possible. The only noticeable change was "Account Admin" became "AccountAdmin" in the report.

API Calls

  • Get a single account from the Accounts API. This returns the account information for the account that the admin is viewing when they click the button
  • Get the sub-accounts of an account from the Accounts API. This returns all of the sub-accounts, but it does not return information on the account itself, which is why the call to get a single account was needed as well. Be sure to specify recursive=1 in the query parameters to get all of the sub-...-sub-accounts.
  • List account admins from the Admins API. This call needs made for every account and sub-account that you have. It includes basic role information for each user, which saves having to make additional calls for the role information.

Method 2: Google Sheet

This is the documentation for the December 9, 2015, version of a Google Sheet that I wrote.

It doesn't provide as much information and it doesn't allow you to specify which sub-accounts to get the list for. It doesn't do any sorting, although it still probably groups by sub-account. It was something quick I threw together one morning.

Google Sheet CSV File


  1. Open up the Google Spreadsheet: List Canvas Admins
  2. This will open the spreadsheet in view-only mode, you need to make your own copy. Go to File > Make a Copy.
  3. There will be new Menu item called "Canvas". It contains the menu. The first thing to do is choose "Configure API Settings". It will ask for authorization. Then put in the hostname of your Canvas instance and an API access token - How do I obtain an API access token for an account?
  4. After you configure that, go to the Canvas menu again and choose either "List All Admins" or "List Only Sub-Account Admins"
  5. Watch the magic occur on a new sheet called "Admins"

Course-level roles are not included

The code here uses API calls that return list of admins for an account. That means that if you have a course-level role it will not show up in this report. Those roles are based on enrollments so you would need to look at every enrollment for every user in every course to see which ones have special roles.

You can obtain course role enrollment data through Canvas Data or through the Provisioning Report from the Admin > Settings > Reports screen. The Canvas Data approach requires extra setup and the information is not live. The Provisioning Report is live when the report was generated, but it runs and then emails you once it's ready.

Neither of these approaches is suitable for invocation through a button in a web browser, were people expect immediate results, or a Google sheet, where there is a script timeout of 5 minutes.