Microsoft Defender for Endpoint Adding Tags for Multiple Devices from CSV List

                                                                                                         Bruno Gabrielli and Tan Tran 


Dear IT Pros, 

Related to Microsoft for Endpoint, recently we got a request from a customer to create the group of tool devices running Windows 10 Operating Systems. This device group later will be assigned with no-remediation policy. Customer has wanted all the devices which are members of this group, will be audited and alerted about threats by Defender Service only, there should be no action such as quarantine or removal of files on the critical devices which were used to control tool in operation rooms.

The task is easy, just need to create a device group based on the device tags, for example, I use the tag name “OP-Tool” and make a dynamic group based on tag name of OP-Tool:



There is a good techblog article about scoping devices based on tags by Steve Newby (Microsoft).

The question is, how could we tag each of the Defender Endpoint Device with the “OP-tool” label?

We need to do the task on tens of thousands of devices programmatically.

As you already knew it, there are a few ways to tag a device, you could tag it manually by Defender Portal under device and manage tag or by Windows Regedit.exe and modifying the device ‘s registry key. Another method is using the Endpoint MDM Configuration Profile with a custom OMA-URI, or by using Defender portal with the API Explorer feature. We could also make device tags easily by using Microsoft Flow. One of Customer preferred way  is tagging device by running PowerShell script with API access to Defender Service data source.

Let us go through the options mentioned above.

  1. Using Registry key to tag devices:

For device tagging purpose, you could create the registry key named “DeviceTagging” based on Microsoft document. The key path and value is as follows:

HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftWindows Advanced Threat ProtectionDeviceTagging

Key name: Group     Value: YourTagName



|where DeviceName contains “fc-cl01”

|where Timestamp > ago(1h)

|where RegistryDeviceTag contains “NewOP-Tool”

|project Timestamp, DeviceName, RegistryDeviceTag, OSPlatform, LoggedOnUsers, MachineGroup

Query Result:


  • There are a few limitations:
    • Only one Tag name is allowed due to the REG_SZ string type. This limitation could be overcome by the API PowerShell Scripting method on which we will discuss later as an alternative option.
    • Tag name should be less than 200 characters.
    • Device Tag Name is only synchronized once per day, to apply change and synchronization to Defender for Endpoint Portal, you will need to restart the device and wait for 15-30 minutes for device to appear in Defender portalDevice Inventory as shown here:



  1. Using Endpoint Manager Configuration Profile to tag devices.
  • Create the Custom OMA-URI:                  ./Device/Vendor/MSFT/WindowsAdvancedThreatProtection/DeviceTagging/Group


  • Assign the profile to Endpoint Manager Group.

3.Using Microsoft Defender for Endpoint API Explorer to tag devices.

Let us start with a simple command in API explorer:

  • Go to, the defender for Endpoint Portal,
  • From the left navigation menu, select Partners & APIs > API Explorer.

To add/remove tag by API explorer:

You just need to run the post command as shown here and replace the device ID with your device ID.

  • To remove a tag


  • To add a tag

Run Post command: 


 Result shown in the Device blade:


  • To get the list of device ID with Tag:

Run Get command:$select=id, computerDnsName,Machinetags


  1. Using PowerShell Script to tag devices:

Antonio Vasconcelos from Git Hub has provided us a script to connect to MD for Endpoint API and tag multiple devices in one shot:

# Author: Antonio Vasconcelos
# Twitter: anthonws
# Date/Version/Changelog:
# 2020-01-25 – 1.0 – First release
# Objective:
# Script that adds a specified Tag to machines in MDATP
# Input is expected to be a CSV file with 2 columns, one with “Name” and the other with “Tag”. The first line are the headers. Break line for each new entry.
# MachineId is obtained via the ComputerDnsName, which should equate to the Host name or FQDN, depending on the type of machine join (WORKGROUP, Domain, etc.)

$tenantId = ‘000000000000000000000' ### Paste your own tenant ID here
$appId = ‘000000000000000000000' ### Paste your own app ID here
$appSecret = ‘000000000000000000000' ### Paste your own app keys here
$resourceAppIdUri = ‘'
$oAuthUri = “$TenantId/oauth2/token”
$authBody = [Ordered] @{
   resource = “$resourceAppIdUri”
    client_id = “$appId”
    client_secret = “$appSecret”
    grant_type = ‘client_credentials'
$authResponse = Invoke-RestMethod -Method Post -Uri $oAuthUri -Body $authBody -ErrorAction Stop
$token = $authResponse.access_token
# Store auth token into header for future use
$headers = @{
        ‘Content-Type' = ‘application/json'
        Accept = ‘application/json'
        Authorization = “Bearer $token”
# Clean variables
$Data = @();
$MachineName = $null;
$MachineTag = $null;
$MachineId = $null;
##### CSV input file serialization ####
$Data = Import-Csv -Path c:TempMDATPMachineList.csv
##### Add Tag Block ####
# Added timer to respect API call limits (100 per minute and 1500 per hour)
# Defaulting to the shortest limit, which is 1500 per hour, which equates to 25 calls per minute
# Introduced a 3 sleep at the beginning of every while iteration
# Iterate over the full array
$Data | foreach {
    Start-Sleep -Seconds 3
    $MachineName = $($_.Name);
    $MachineTag = $($_.Tag);
    # Obtain the MachineId from MDATP, based on the ComputerDnsName present in the CSV file
    $url = “$MachineName”  
    $webResponse = Invoke-RestMethod -Method Get -Uri $url -Headers $headers -ErrorAction Stop
    $MachineId = $;
    # Body content will carry the tag specified in the CSV file for the given machine
    $body = @{
    # Add specified tag in CSV to the particular MachineId in MDATP
    $url = “$MachineId/tags” 
    $webResponse = Invoke-WebRequest -Method Post -Uri $url -Headers $headers -Body ($body|ConvertTo-Json) -ContentType “application/json” -ErrorAction Stop
    # Clean variables (sanity check)
    $MachineName = $null;
    $MachineTag = $null;
    $MachineId = $null;

Prepared steps to run the “Device Tagging” API script:

  • Prerequisite: Before you can run the API script, you need to setup the App API and permissions in for your “Microsoft Defender for Endpoint” App
  • Register an API for your MD for Endpoint ( named Windows Defender in )


  • Assign API permission for Microsoft Threat Protection
  • Choose “API my organization uses”
  • In the search box type WindowsDefenderATP as shown:


  • Assign Application permission, Read and Write Machine Information:


  • Grant Admin Consent  :


  • Click Yes to confirm:


  • In the script, you will need to replace the App ID number with your MDfE App ID, replace Tenant ID and App Secret Key accordingly. You could get them from API Registration as shown here:


  • Double click to open the related App.
  • Copy the App ID and Tenant ID:


  • Go to Certificates & secret, copy the secret key:


  • You need to create machinelist.csv with all the devices needed to tag and their tag names, Multiple tags for the same device will need multiple rows.

       Sample of machinelist.csv:


Results after running PowerShell tagging script, multiple tags are added to the existing device tags as shown here:


  1. Using Microsoft Flow to tag devices:

Tomer Brand from Microsoft show us easily tag multiple devices by Microsoft flow in the following techblog article:

I hope the information is helpful and save you some precious time when tagging Defender Devices.

Until next time!



The sample are not supported under any Microsoft standard support program or service. The sample are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.


This article was originally published by Microsoft's SQL Server Blog. You can find the original article here.