diff --git a/PiHoleShell/PiHoleShell.psm1 b/PiHoleShell/PiHoleShell.psm1
index 85b431d..72c39c0 100644
--- a/PiHoleShell/PiHoleShell.psm1
+++ b/PiHoleShell/PiHoleShell.psm1
@@ -38,7 +38,7 @@ Export-ModuleMember -Function @(
#History
'Get-PiHoleHistory', 'Get-PiHoleHistoryDatabase', 'Get-PiHoleHistoryClient', 'Get-PiHoleHistoryDatabaseClient', `
#Teleporter
- 'Get-PiHoleTeleporterDownload', `
+ 'Get-PiHoleTeleporterDownload', 'Import-PiHoleTeleporter', `
#DomainManagement
'Get-PiHoleDomain', 'New-PiHoleDomain', 'Update-PiHoleDomain', 'Remove-PiHoleDomain', `
#ClientManagement
diff --git a/PiHoleShell/Public/Teleporter/Import-PiHoleTeleporter.ps1 b/PiHoleShell/Public/Teleporter/Import-PiHoleTeleporter.ps1
new file mode 100644
index 0000000..a9471d0
--- /dev/null
+++ b/PiHoleShell/Public/Teleporter/Import-PiHoleTeleporter.ps1
@@ -0,0 +1,165 @@
+function Import-PiHoleTeleporter {
+ <#
+.SYNOPSIS
+Import Pi-hole settings
+
+.DESCRIPTION
+Uploads a Teleporter archive (as produced by Get-PiHoleTeleporterDownload) to restore Pi-hole
+from it. This overwrites your current configuration, so unlike most functions in this module it
+prompts for confirmation by default - pass -Confirm:$false to skip the prompt, or -WhatIf to see
+what would happen without making any change.
+
+By default every importable item in the archive is restored. Pass one or more of the switch
+parameters below to import only those specific items instead - anything not switched on is left
+alone.
+
+.PARAMETER PiHoleServer
+The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100"
+
+.PARAMETER Password
+The API Password you generated from your PiHole server
+
+.PARAMETER FilePath
+Path to the Teleporter .zip archive to upload
+
+.PARAMETER Config
+Import Pi-hole's configuration
+
+.PARAMETER DhcpLeases
+Import Pi-hole's DHCP leases
+
+.PARAMETER Group
+Import Pi-hole's groups table
+
+.PARAMETER Adlist
+Import Pi-hole's adlist table
+
+.PARAMETER AdlistByGroup
+Import Pi-hole's table relating adlist entries to groups
+
+.PARAMETER Domainlist
+Import Pi-hole's domainlist table
+
+.PARAMETER DomainlistByGroup
+Import Pi-hole's table relating domainlist entries to groups
+
+.PARAMETER Client
+Import Pi-hole's client table
+
+.PARAMETER ClientByGroup
+Import Pi-hole's table relating client entries to groups
+
+.PARAMETER IgnoreSsl
+Set to $true to skip SSL certificate validation
+
+.PARAMETER RawOutput
+This will dump the response instead of the formatted object
+
+.EXAMPLE
+Import-PiHoleTeleporter -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" -FilePath "C:\Backups\pihole-backup.zip"
+
+.EXAMPLE
+Import-PiHoleTeleporter -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" -FilePath "C:\Backups\pihole-backup.zip" -Group -Adlist -AdlistByGroup
+
+.EXAMPLE
+Import-PiHoleTeleporter -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" -FilePath "C:\Backups\pihole-backup.zip" -WhatIf
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High', HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/teleporter')]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")]
+ param (
+ [Parameter(Mandatory = $true)]
+ [System.URI]$PiHoleServer,
+ [Parameter(Mandatory = $true)]
+ [string]$Password,
+ [Parameter(Mandatory = $true)]
+ [System.IO.FileInfo]$FilePath,
+ [switch]$Config,
+ [switch]$DhcpLeases,
+ [switch]$Group,
+ [switch]$Adlist,
+ [switch]$AdlistByGroup,
+ [switch]$Domainlist,
+ [switch]$DomainlistByGroup,
+ [switch]$Client,
+ [switch]$ClientByGroup,
+ [bool]$IgnoreSsl = $false,
+ [bool]$RawOutput = $false
+ )
+ try {
+ if (-not (Test-Path -Path $FilePath)) {
+ throw "$FilePath does not exist!"
+ }
+
+ # Flat switches rather than Pi-hole's own nested { config, dhcp_leases, gravity: {...} }
+ # shape - whether any were passed at all decides whether an "import" field is sent; if
+ # none were, the field is omitted entirely so Pi-hole imports everything (its own default
+ # when the field is missing), matching this function's own "import everything" default.
+ $ImportSwitchNames = 'Config', 'DhcpLeases', 'Group', 'Adlist', 'AdlistByGroup', 'Domainlist', 'DomainlistByGroup', 'Client', 'ClientByGroup'
+ $AnySwitchSpecified = $false
+ foreach ($Name in $ImportSwitchNames) {
+ if ($PSBoundParameters.ContainsKey($Name)) {
+ $AnySwitchSpecified = $true
+ break
+ }
+ }
+
+ $Target = "Pi-Hole at $PiHoleServer"
+ $Action = "Import Teleporter archive '$FilePath' (this will overwrite your current configuration)"
+ if ($PSCmdlet.ShouldProcess($Target, $Action)) {
+ $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl
+
+ $FormData = @{
+ file = Get-Item -Path $FilePath
+ }
+
+ if ($AnySwitchSpecified) {
+ $ImportBody = [ordered]@{
+ config = [bool]$Config
+ dhcp_leases = [bool]$DhcpLeases
+ gravity = [ordered]@{
+ group = [bool]$Group
+ adlist = [bool]$Adlist
+ adlist_by_group = [bool]$AdlistByGroup
+ domainlist = [bool]$Domainlist
+ domainlist_by_group = [bool]$DomainlistByGroup
+ client = [bool]$Client
+ client_by_group = [bool]$ClientByGroup
+ }
+ }
+ $FormData['import'] = $ImportBody | ConvertTo-Json -Depth 5 -Compress
+ }
+
+ $Params = @{
+ Headers = @{sid = $($Sid) }
+ Uri = "$($PiHoleServer.OriginalString)/api/teleporter"
+ Method = "Post"
+ SkipCertificateCheck = $IgnoreSsl
+ Form = $FormData
+ }
+
+ $Response = Invoke-RestMethod @Params
+
+ if ($RawOutput) {
+ Write-Output $Response
+ }
+ else {
+ # The live API returns this array under "files", despite the OpenAPI spec
+ # documenting the field as "processed" - confirmed against a real server.
+ $Object = [PSCustomObject]@{
+ Processed = $Response.files
+ }
+ Write-Output $Object
+ }
+ }
+ }
+
+ catch {
+ Write-Error -Message $_.Exception.Message
+ }
+
+ finally {
+ if ($Sid) {
+ Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl
+ }
+ }
+}
diff --git a/README.md b/README.md
index 7a4e239..188f251 100644
--- a/README.md
+++ b/README.md
@@ -192,6 +192,7 @@ See [docs/EXAMPLES.md](docs/EXAMPLES.md) for real, captured output from every fu
| `Get-PiHoleNetworkRoute` | Get info about the routes of your Pi-hole |
| `Get-PiHolePadd` | Get summarized data for PADD |
| `Get-PiHoleTeleporterDownload` | Export Pi-hole settings |
+| `Import-PiHoleTeleporter` | Import Pi-hole settings |
| `Remove-PiHoleConfigArrayItem` | Delete config array item |
| `Remove-PiHoleDhcpLease` | Remove a DHCP lease |
| `Remove-PiHoleInfoMessage` | Delete a Pi-hole diagnosis message |
diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md
index a701363..0602c4e 100644
--- a/docs/EXAMPLES.md
+++ b/docs/EXAMPLES.md
@@ -99,9 +99,9 @@ New-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -GroupName "PiHo
Name : PiHoleShellDocsExampleGroup
Comment : Example group
Enabled : True
-Id : 57
-DateAdded : 10/1/2026 3:13:46 PM
-DateModified : 10/1/2026 3:13:46 PM
+Id : 63
+DateAdded : 10/6/2026 10:06:30 PM
+DateModified : 10/6/2026 10:06:30 PM
```
### Get-PiHoleGroup
@@ -143,9 +143,9 @@ DateModified : 9/30/2026 8:48:26 AM
Name : PiHoleShellDocsExampleGroup
Comment : Example group
Enabled : True
-Id : 57
-DateAdded : 10/1/2026 3:13:46 PM
-DateModified : 10/1/2026 3:13:46 PM
+Id : 63
+DateAdded : 10/6/2026 10:06:30 PM
+DateModified : 10/6/2026 10:06:30 PM
```
### Update-PiHoleGroup
@@ -159,9 +159,9 @@ Update-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -GroupName "P
Name : PiHoleShellDocsExampleGroup
Comment : Example group
Enabled : False
-Id : 57
-DateAdded : 10/1/2026 3:13:46 PM
-DateModified : 10/1/2026 3:14:04 PM
+Id : 63
+DateAdded : 10/6/2026 10:06:30 PM
+DateModified : 10/6/2026 10:06:48 PM
```
### Remove-PiHoleGroup
@@ -190,9 +190,9 @@ Address : https://blocklistproject.github.io/Lists/alt-version/ransomware
Comment : Example list
Groups : {Default}
Enabled : True
-Id : 71
-DateAdded : 10/1/2026 3:14:41 PM
-DateModified : 10/1/2026 3:14:41 PM
+Id : 81
+DateAdded : 10/6/2026 10:07:25 PM
+DateModified : 10/6/2026 10:07:25 PM
Type : Block
DateUpdated :
Number : 0
@@ -218,7 +218,7 @@ DateAdded : 7/6/2025 2:20:13 AM
DateModified : 7/6/2025 2:20:13 AM
Type : block
DateUpdated : 7/6/2025 2:20:13 AM
-Number : 74761
+Number : 72234
InvalidDomains : 1
AbpEntries : 0
Status : 2
@@ -246,7 +246,7 @@ DateAdded : 7/6/2025 2:20:46 AM
DateModified : 7/6/2025 2:20:46 AM
Type : block
DateUpdated : 7/6/2025 2:20:46 AM
-Number : 175912
+Number : 176582
InvalidDomains : 0
AbpEntries : 0
Status : 2
@@ -294,9 +294,9 @@ Address : https://blocklistproject.github.io/Lists/alt-version/ransomware
Comment : Example list
Groups : {Default}
Enabled : False
-Id : 71
-DateAdded : 10/1/2026 3:14:41 PM
-DateModified : 10/1/2026 3:15:14 PM
+Id : 81
+DateAdded : 10/6/2026 10:07:25 PM
+DateModified : 10/6/2026 10:07:58 PM
Type : Block
DateUpdated :
Number : 0
@@ -322,8 +322,8 @@ Type : block
Groups : {0}
DateAdded : 7/6/2025 2:20:13 AM
DateModified : 7/6/2025 2:20:13 AM
-DateUpdated : 9/26/2026 11:28:08 PM
-Number : 74761
+DateUpdated : 10/2/2026 9:10:24 PM
+Number : 72234
InvalidDomains : 1
AbpEntries : 0
Status : 2
@@ -352,8 +352,8 @@ Type : block
Groups : {0}
DateAdded : 7/6/2025 2:20:46 AM
DateModified : 7/6/2025 2:20:46 AM
-DateUpdated : 9/30/2026 10:20:00 AM
-Number : 175912
+DateUpdated : 10/2/2026 9:43:40 AM
+Number : 176582
InvalidDomains : 0
AbpEntries : 0
Status : 2
@@ -421,9 +421,9 @@ Kind : Exact
Comment : Example domain
Groups : {Default}
Enabled : True
-Id : 22
-DateAdded : 10/1/2026 3:15:52 PM
-DateModified : 10/1/2026 3:15:52 PM
+Id : 18
+DateAdded : 10/6/2026 10:08:36 PM
+DateModified : 10/6/2026 10:08:36 PM
```
### Get-PiHoleDomain
@@ -441,9 +441,9 @@ Kind : exact
Comment : Example domain
Groups : {Default}
Enabled : True
-Id : 22
-DateAdded : 10/1/2026 3:15:52 PM
-DateModified : 10/1/2026 3:15:52 PM
+Id : 18
+DateAdded : 10/6/2026 10:08:36 PM
+DateModified : 10/6/2026 10:08:36 PM
```
### Update-PiHoleDomain
@@ -461,9 +461,9 @@ Kind : Exact
Comment : Example domain
Groups : {Default}
Enabled : False
-Id : 22
-DateAdded : 10/1/2026 3:15:52 PM
-DateModified : 10/1/2026 3:16:25 PM
+Id : 18
+DateAdded : 10/6/2026 10:08:36 PM
+DateModified : 10/6/2026 10:09:10 PM
```
### Remove-PiHoleDomain
@@ -494,9 +494,9 @@ Client : 192.168.99.99
Name :
Comment : Example client
Groups : {Default}
-Id : 22
-DateAdded : 10/1/2026 3:16:56 PM
-DateModified : 10/1/2026 3:16:56 PM
+Id : 20
+DateAdded : 10/6/2026 10:09:40 PM
+DateModified : 10/6/2026 10:09:40 PM
```
### Get-PiHoleClient
@@ -511,9 +511,9 @@ Client : 192.168.99.99
Name :
Comment : Example client
Groups : {Default}
-Id : 22
-DateAdded : 10/1/2026 3:16:56 PM
-DateModified : 10/1/2026 3:16:56 PM
+Id : 20
+DateAdded : 10/6/2026 10:09:40 PM
+DateModified : 10/6/2026 10:09:40 PM
```
### Get-PiHoleClientSuggestion
@@ -526,13 +526,13 @@ Get-PiHoleClientSuggestion -PiHoleServer $PiHoleServer -Password $Password
HwAddr : ip-127.0.0.1
MacVendor :
-LastQuery : 10/1/2026 3:00:00 PM
+LastQuery : 10/6/2026 10:06:14 PM
Addresses : 127.0.0.1
Names : localhost
HwAddr : 74:56:3c:bb:f4:0b
MacVendor : Giga-Byte Technology Co.,Ltd.
-LastQuery : 10/1/2026 9:03:33 AM
+LastQuery : 10/6/2026 10:03:16 PM
Addresses : 192.168.1.162
Names :
```
@@ -549,9 +549,9 @@ Client : 192.168.99.99
Name :
Comment : Updated comment
Groups : {Default}
-Id : 22
-DateAdded : 10/1/2026 3:16:56 PM
-DateModified : 10/1/2026 3:17:35 PM
+Id : 20
+DateAdded : 10/6/2026 10:09:40 PM
+DateModified : 10/6/2026 10:10:18 PM
```
### Remove-PiHoleClient
@@ -576,18 +576,18 @@ Get-PiHoleStatsSummary -PiHoleServer $PiHoleServer -Password $Password
```
-Total : 52
-Blocked : 10
-PercentBlocked : 19.230770111084
-UniqueDomains : 15
+Total : 72
+Blocked : 8
+PercentBlocked : 11.1111106872559
+UniqueDomains : 16
Forwarded : 27
-Cached : 15
+Cached : 37
Frequency : 0
-Types : @{A=20; AAAA=19; ANY=0; SRV=0; SOA=0; PTR=13; TXT=0; NAPTR=0; MX=0; DS=0; RRSIG=0; DNSKEY=0; NS=0; SVCB=0; HTTPS=0; OTHER=0}
-Status : @{Unknown=0; Gravity=10; Forwarded=27; Cache=15; Regex=0; DenyList=0; ExternalBlockedIp=0; ExternalBlockedNull=0; ExternalBlockedNxra=0; GravityCname=0; RegexCname=0; DenyListCname=0; Retired=0; RetiredDnssec=0; InProgress=0; Dbbusy=0; SpecialDomain=0; CacheStale=0; ExternalBlockedEde15=0}
-Replies : @{Unknown=10; Nodata=3; Nxdomain=3; Cname=0; Ip=26; Domain=10; Rrname=0; ServFail=0; Refused=0; Notimp=0; Other=0; Dnssec=0; None=0; Blob=0}
+Types : @{A=18; AAAA=17; ANY=0; SRV=0; SOA=0; PTR=37; TXT=0; NAPTR=0; MX=0; DS=0; RRSIG=0; DNSKEY=0; NS=0; SVCB=0; HTTPS=0; OTHER=0}
+Status : @{Unknown=0; Gravity=8; Forwarded=27; Cache=37; Regex=0; DenyList=0; ExternalBlockedIp=0; ExternalBlockedNull=0; ExternalBlockedNxra=0; GravityCname=0; RegexCname=0; DenyListCname=0; Retired=0; RetiredDnssec=0; InProgress=0; Dbbusy=0; SpecialDomain=0; CacheStale=0; ExternalBlockedEde15=0}
+Replies : @{Unknown=7; Nodata=3; Nxdomain=2; Cname=0; Ip=25; Domain=35; Rrname=0; ServFail=0; Refused=0; Notimp=0; Other=0; Dnssec=0; None=0; Blob=0}
Clients : @{Active=2; Total=2}
-Gravity : @{DomainsBeingBlocked=495564; LastUpdate=1790861541}
+Gravity : @{DomainsBeingBlocked=526957; LastUpdate=1791140144}
```
### Get-PiHoleStatsRecentBlocked
@@ -598,7 +598,7 @@ Get-PiHoleStatsRecentBlocked -PiHoleServer $PiHoleServer -Password $Password
```
-Blocked : googleadservices.com
+Blocked : googlesyndication.com
```
### Get-PiHoleStatsQueryType
@@ -610,10 +610,10 @@ Get-PiHoleStatsQueryType -PiHoleServer $PiHoleServer -Password $Password
```
Type : A
-Count : 20
+Count : 18
Type : AAAA
-Count : 19
+Count : 17
Type : ANY
Count : 0
@@ -636,18 +636,18 @@ Get-PiHoleStatsTopDomain -PiHoleServer $PiHoleServer -Password $Password
```
Domain : 1.0.0.127.in-addr.arpa
-Count : 7
+Count : 31
-Domain : example.com
+Domain : bbc.com
Count : 4
-Domain : cloudflare.com
+Domain : example.com
Count : 4
-Domain : reddit.com
+Domain : python.org
Count : 4
-Domain : bbc.com
+Domain : wikipedia.org
Count : 4
_(showing 5 of 10 results)_
@@ -661,13 +661,13 @@ Get-PiHoleStatsTopClient -PiHoleServer $PiHoleServer -Password $Password
```
-IP : 192.168.1.162
-Name :
-Count : 39
-
IP : 127.0.0.1
Name : localhost
-Count : 13
+Count : 37
+
+IP : 192.168.1.162
+Name :
+Count : 35
```
### Get-PiHoleStatsUpstream
@@ -678,9 +678,9 @@ Get-PiHoleStatsUpstream -PiHoleServer $PiHoleServer -Password $Password
```
-TotalQueries : 52
+TotalQueries : 72
ForwardedQueries : 27
-Upstreams : {@{Ip=blocklist; Name=blocklist; Port=-1; Count=10; ResponseTime=0; Variance=0}, @{Ip=cache; Name=cache; Port=-1; Count=15; ResponseTime=0; Variance=0}, @{Ip=8.8.8.8; Name=dns.google; Port=53; Count=27; ResponseTime=0.0202921777963638; Variance=0.00264818341859654}}
+Upstreams : {@{Ip=blocklist; Name=blocklist; Port=-1; Count=8; ResponseTime=0; Variance=0}, @{Ip=cache; Name=cache; Port=-1; Count=37; ResponseTime=0; Variance=0}, @{Ip=8.8.4.4; Name=dns.google; Port=53; Count=23; ResponseTime=0; Variance=0}, @{Ip=8.8.8.8; Name=dns.google; Port=53; Count=4; ResponseTime=0; Variance=0}}
```
### Get-PiHoleStatsQuerySuggestions
@@ -691,10 +691,10 @@ Get-PiHoleStatsQuerySuggestions -PiHoleServer $PiHoleServer -Password $Password
```
-Domain : {1.0.0.127.in-addr.arpa, example.com, cloudflare.com, reddit.com…}
-ClientIp : {192.168.1.162, 127.0.0.1}
+Domain : {1.0.0.127.in-addr.arpa, bbc.com, example.com, python.org…}
+ClientIp : {127.0.0.1, 192.168.1.162}
ClientName : {localhost}
-Upstream : {blocklist, cache, 8.8.8.8#53 (dns.google), permitted}
+Upstream : {blocklist, cache, 8.8.4.4#53 (dns.google), 8.8.8.8#53 (dns.google)…}
Type : {A, AAAA, ANY, SRV…}
Status : {UNKNOWN, GRAVITY, FORWARDED, CACHE…}
Reply : {UNKNOWN, NODATA, NXDOMAIN, CNAME…}
@@ -711,10 +711,10 @@ Get-PiHoleStatsDatabaseSummary -PiHoleServer $PiHoleServer -Password $Password
```
-SumQueries : 52
-SumBlocked : 10
-PercentBlocked : 19.230770111084
-TotalClients : 3
+SumQueries : 56
+SumBlocked : 8
+PercentBlocked : 14.2857141494751
+TotalClients : 2
```
### Get-PiHoleStatsDatabaseQueryType
@@ -728,7 +728,7 @@ Get-PiHoleStatsDatabaseQueryType -PiHoleServer $PiHoleServer -Password $Password
```
Type : A
-Count : 19
+Count : 17
Type : AAAA
Count : 0
@@ -740,7 +740,7 @@ Type : SRV
Count : 0
Type : SOA
-Count : 13
+Count : 21
_(showing 5 of 16 results)_
```
@@ -756,7 +756,10 @@ Get-PiHoleStatsDatabaseTopDomain -PiHoleServer $PiHoleServer -Password $Password
```
Domain : 1.0.0.127.in-addr.arpa
-Count : 7
+Count : 15
+
+Domain : python.org
+Count : 4
Domain : bbc.com
Count : 4
@@ -767,9 +770,6 @@ Count : 4
Domain : example.com
Count : 4
-Domain : stackoverflow.com
-Count : 4
-
_(showing 5 of 10 results)_
```
@@ -785,15 +785,11 @@ Get-PiHoleStatsDatabaseTopClient -PiHoleServer $PiHoleServer -Password $Password
IP : 192.168.1.162
Name :
-Count : 29
+Count : 27
IP : 127.0.0.1
Name : localhost
-Count : 11
-
-IP : 127.0.0.1
-Name :
-Count : 2
+Count : 21
```
### Get-PiHoleStatsDatabaseUpstream
@@ -806,9 +802,9 @@ Get-PiHoleStatsDatabaseUpstream -PiHoleServer $PiHoleServer -Password $Password
```
-TotalQueries : 52
+TotalQueries : 56
ForwardedQueries : 27
-Upstreams : {@{Ip=2; Name=; Port=4294967295; Count=27; ResponseTime=0; Variance=0}, @{Ip=cache; Name=cache; Port=-1; Count=15; ResponseTime=0; Variance=0}, @{Ip=blocklist; Name=blocklist; Port=-1; Count=10; ResponseTime=0; Variance=0}}
+Upstreams : {@{Ip=1; Name=; Port=-1; Count=23; ResponseTime=0; Variance=0}, @{Ip=2; Name=; Port=-1; Count=4; ResponseTime=0; Variance=0}, @{Ip=cache; Name=cache; Port=-1; Count=21; ResponseTime=0; Variance=0}, @{Ip=blocklist; Name=blocklist; Port=-1; Count=8; ResponseTime=0; Variance=0}}
```
### Get-PiHoleQuery
@@ -821,69 +817,69 @@ Get-PiHoleQuery -PiHoleServer $PiHoleServer -Password $Password -Length 5
```
-Id : 51
-Time : 10/1/2026 3:00:00 PM
+Id : 394
+Time : 10/6/2026 10:06:15 PM
Type : PTR
-Domain : 1.0.0.127.in-addr.arpa
+Domain : 4.4.8.8.in-addr.arpa
Cname :
-Status : CACHE
+Status : FORWARDED
Client : @{Ip=127.0.0.1; Name=localhost}
Dnssec : UNKNOWN
-Reply : @{Type=DOMAIN; Time=0.000154972076416016}
+Reply : @{Type=DOMAIN; Time=0.0241849422454834}
ListId :
-Upstream :
+Upstream : 8.8.8.8#53
Ede : @{Code=-1; Text=}
-Id : 50
-Time : 10/1/2026 2:00:01 PM
+Id : 393
+Time : 10/6/2026 10:06:15 PM
Type : PTR
-Domain : 1.0.0.127.in-addr.arpa
+Domain : 8.8.8.8.in-addr.arpa
Cname :
-Status : CACHE
+Status : FORWARDED
Client : @{Ip=127.0.0.1; Name=localhost}
Dnssec : UNKNOWN
-Reply : @{Type=DOMAIN; Time=0.000155925750732422}
+Reply : @{Type=DOMAIN; Time=0.0249054431915283}
ListId :
-Upstream :
+Upstream : 8.8.8.8#53
Ede : @{Code=-1; Text=}
-Id : 49
-Time : 10/1/2026 1:00:00 PM
+Id : 392
+Time : 10/6/2026 10:06:15 PM
Type : PTR
-Domain : 1.0.0.127.in-addr.arpa
+Domain : 162.1.168.192.in-addr.arpa
Cname :
Status : CACHE
Client : @{Ip=127.0.0.1; Name=localhost}
Dnssec : UNKNOWN
-Reply : @{Type=DOMAIN; Time=0.000154018402099609}
+Reply : @{Type=NXDOMAIN; Time=0.0157008171081543}
ListId :
Upstream :
Ede : @{Code=-1; Text=}
-Id : 48
-Time : 10/1/2026 12:00:00 PM
+Id : 391
+Time : 10/6/2026 10:06:15 PM
Type : PTR
Domain : 1.0.0.127.in-addr.arpa
Cname :
Status : CACHE
Client : @{Ip=127.0.0.1; Name=localhost}
Dnssec : UNKNOWN
-Reply : @{Type=DOMAIN; Time=0.000212192535400391}
+Reply : @{Type=DOMAIN; Time=0.0260829925537109}
ListId :
Upstream :
Ede : @{Code=-1; Text=}
-Id : 47
-Time : 10/1/2026 11:00:01 AM
+Id : 390
+Time : 10/6/2026 10:03:17 PM
Type : PTR
-Domain : 8.8.8.8.in-addr.arpa
+Domain : 4.4.8.8.in-addr.arpa
Cname :
-Status : CACHE
+Status : FORWARDED
Client : @{Ip=127.0.0.1; Name=localhost}
Dnssec : UNKNOWN
-Reply : @{Type=DOMAIN; Time=0.00014805793762207}
+Reply : @{Type=DOMAIN; Time=0.0180368423461914}
ListId :
-Upstream :
+Upstream : 8.8.4.4#53
Ede : @{Code=-1; Text=}
```
@@ -916,9 +912,27 @@ Get-PiHoleConfigProperty -PiHoleServer $PiHoleServer -Password $Password
```
-Key : misc.readOnly
+Key : webserver.advancedOpts
+Reason : read_only
+Description : Variable can only be set in pihole.toml, through an environment variable or using pihole-FTL --config, not via API
+
+Key : webserver.paths.webroot
Reason : read_only
-Description : Variable can only be set in pihole.toml, not via API
+Description : Variable can only be set in pihole.toml, through an environment variable or using pihole-FTL --config, not via API
+
+Key : webserver.paths.webhome
+Reason : read_only
+Description : Variable can only be set in pihole.toml, through an environment variable or using pihole-FTL --config, not via API
+
+Key : webserver.paths.prefix
+Reason : read_only
+Description : Variable can only be set in pihole.toml, through an environment variable or using pihole-FTL --config, not via API
+
+Key : misc.dnsmasq_lines
+Reason : read_only
+Description : Variable can only be set in pihole.toml, through an environment variable or using pihole-FTL --config, not via API
+
+_(showing 5 of 6 results)_
```
### Set-PiHoleConfig
@@ -978,18 +992,18 @@ CpuPercent : 0
MemoryPercent : 0
ActiveClients : 2
Blocking : enabled
-Cache : @{Size=10000; Inserted=35; Evicted=0}
+Cache : @{Size=10000; Inserted=34; Evicted=0}
Config : @{DhcpActive=False; DhcpStart=; DhcpEnd=; DhcpIpv6=False; DnsDnssec=False; DnsDomain=lan; DnsNumUpstreams=2; DnsPort=53; DnsrevServerAactive=False; PrivacyLevel=0}
-GravitySize : 495564
+GravitySize : 526957
HostModel : Raspberry Pi Zero W Rev 1.1
IFace : @{v4=; v6=}
NodeName : dns3.localdomain
-Pid : 388
-Queries : @{Total=52; Blocked=10; PercentBlocked=19.230770111084; QueryFrequency=0}
-RecentBlocked : googleadservices.com
-Sensors : @{CpuTemp=39.546; HotLimit=60; Unit=C}
-System : @{Uptime=235882; Memory=; Procs=72; Cpu=; Ftl=}
-TopBlocked : googleadservices.com
+Pid : 389
+Queries : @{Total=69; Blocked=8; PercentBlocked=11.5942029953003; QueryFrequency=0}
+RecentBlocked : googlesyndication.com
+Sensors : @{CpuTemp=40.622; HotLimit=60; Unit=C}
+System : @{Uptime=384699; Memory=; Procs=70; Cpu=; Ftl=}
+TopBlocked : analytics.google.com
TopClient : 192.168.1.162
TopDomain : 1.0.0.127.in-addr.arpa
Version : @{Core=; Web=; Ftl=; Docker=}
@@ -1028,11 +1042,11 @@ Get-PiHoleInfoSystem -PiHoleServer $PiHoleServer -Password $Password
```
-Uptime : 235892
+Uptime : 384709
Memory : @{Ram=; Swap=}
-Procs : 74
-Cpu : @{NumProcessors=1; PercentCpu=97.1999969482422; Load=}
-Ftl : @{PercentMemory=2.52266621589661; PercentCpu=96.4000015258789}
+Procs : 70
+Cpu : @{NumProcessors=1; PercentCpu=96.8000030517578; Load=}
+Ftl : @{PercentMemory=3.02243185043335; PercentCpu=96.5}
```
### Get-PiHoleInfoFtl
@@ -1043,16 +1057,16 @@ Get-PiHoleInfoFtl -PiHoleServer $PiHoleServer -Password $Password
```
-Database : @{Gravity=495564; Antigravity=0; Groups=4; Lists=14; Clients=0; Domains=; Regex=}
+Database : @{Gravity=526957; Antigravity=0; Groups=4; Lists=14; Clients=0; Domains=; Regex=}
PrivacyLevel : 0
QueryFrequency : 0
Clients : @{Total=2; Active=2}
-Pid : 388
-Uptime : 24254906.207769
-PercentMemory : 2.52266621589661
-PercentCpu : 96.4000015258789
+Pid : 389
+Uptime : 528324.275473
+PercentMemory : 3.02243185043335
+PercentCpu : 96.5
AllowDestructive : True
-Dnsmasq : @{DnsCacheInserted=35; DnsCacheLiveFreed=0; DnsQueriesForwarded=27; DnsAuthAnswered=0; DnsLocalAnswered=25; DnsStaleAnswered=0; DnsUnanswered=0; DnssecMaxCryptoUse=0; DnssecMaxSigFail=0; DnssecMaxWork=0; Bootp=0; Pxe=0; DhcpAck=0; DhcpDecline=0; DhcpDiscover=0; DhcpInform=0; DhcpNak=0; DhcpOffer=0; DhcpRelease=0; DhcpRequest=0; Noanswer=0; LeasesAllocated4=0; LeasesPruned4=0; LeasesAllocated6=0; LeasesPruned6=0; TcpConnections=0; DhcpLeasequery=0; DhcpLeaseUnassigned=0; DhcpLeaseActve=0; DhcpLeaseUnknown=0}
+Dnsmasq : @{DnsCacheInserted=34; DnsCacheLiveFreed=0; DnsQueriesForwarded=25; DnsAuthAnswered=0; DnsLocalAnswered=15; DnsStaleAnswered=0; DnsUnanswered=0; DnssecMaxCryptoUse=0; DnssecMaxSigFail=0; DnssecMaxWork=0; Bootp=0; Pxe=0; DhcpAck=0; DhcpDecline=0; DhcpDiscover=0; DhcpInform=0; DhcpNak=0; DhcpOffer=0; DhcpRelease=0; DhcpRequest=0; Noanswer=0; LeasesAllocated4=0; LeasesPruned4=0; LeasesAllocated6=0; LeasesPruned6=0; TcpConnections=0; DhcpLeasequery=0; DhcpLeaseUnassigned=0; DhcpLeaseActve=0; DhcpLeaseUnknown=0}
```
### Get-PiHoleInfoSensors
@@ -1064,7 +1078,7 @@ Get-PiHoleInfoSensors -PiHoleServer $PiHoleServer -Password $Password
```
List : {@{Name=cpu_thermal; Path=hwmon0; Source=devices/virtual/thermal/thermal_zone0; Temps=}, @{Name=rpi_volt; Path=hwmon1; Source=devices/platform/soc/soc:firmware/raspberrypi-hwmon; Temps=}}
-CpuTemp : 40.084
+CpuTemp : 41.16
HotLimit : 60
Unit : C
```
@@ -1081,13 +1095,13 @@ Size : 13983744
Type : Regular file
Mode : rw-r-----
AccessTime : 6/25/2025 12:32:44 AM
-ModifiedTime : 10/1/2026 2:06:00 PM
-ChangeTime : 10/1/2026 2:06:00 PM
+ModifiedTime : 10/6/2026 9:56:20 PM
+ChangeTime : 10/6/2026 9:56:20 PM
Owner : @{User=; Group=}
-Queries : 52
-EarliestTimestamp : 9/30/2026 3:10:00 PM
-QueriesDisk : 52
-EarliestTimestampDisk :
+Queries : 69
+EarliestTimestamp : 10/5/2026 10:00:00 PM
+QueriesDisk : 391
+EarliestTimestampDisk : 10/4/2026 2:31:09 PM
SqliteVersion : 3.53.1
```
@@ -1154,18 +1168,7 @@ Get-PiHoleInfoMessage -PiHoleServer $PiHoleServer -Password $Password
```
```
-
-Id : 1
-Timestamp : 10/1/2026 8:28:21 AM
-Type : LIST
-Plain : List with ID 63 (https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/domains/light.txt) was inaccessible during last gravity run
-Html : List with ID 63 (https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/domains/light.txt) was inaccessible during last gravity run
-
-Id : 2
-Timestamp : 10/1/2026 9:38:21 AM
-Type : LOAD
-Plain : Long-term load (15min avg) larger than number of processors: 1.0 > 1
-Html : Long-term load (15min avg) larger than number of processors: 1.0 > 1
This may slow down DNS resolution and can cause bottlenecks.
+(no output)
```
### Get-PiHoleInfoMessageCount
@@ -1176,7 +1179,7 @@ Get-PiHoleInfoMessageCount -PiHoleServer $PiHoleServer -Password $Password
```
-Count : 2
+Count : 0
```
### Remove-PiHoleInfoMessage
@@ -1200,9 +1203,9 @@ Get-PiHoleLogWebserver -PiHoleServer $PiHoleServer -Password $Password
```
-Log : {@{Timestamp=10/1/2026 8:28:22 AM; Message=Initializing HTTP server on ports "8089,8489s"; Priority=}, @{Timestamp=10/1/2026 8:31:16 AM; Message=ACCESS: 192.168.1.162 - - [01/Oct/2026:13:31:15 +0000] "PATCH /api/config?restart=false HTTP/1.1" 200 4588 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}, @{Timestamp=10/1/2026 8:31:17 AM; Message=ACCESS: 192.168.1.162 - - [01/Oct/2026:13:31:16 +0000] "DELETE /api/auth HTTP/1.1" 204 558 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}, @{Timestamp=10/1/2026 8:31:26 AM; Message=ACCESS: 192.168.1.162 - - [01/Oct/2026:13:31:17 +0000] "POST /api/auth HTTP/1.1" 200 807 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}…}
-NextID : 31
-Pid : 388
+Log : {@{Timestamp=10/6/2026 9:56:22 PM; Message=Initializing HTTP server on ports "8089,8489s"; Priority=}, @{Timestamp=10/6/2026 10:04:28 PM; Message=ACCESS: 192.168.1.162 - - [07/Oct/2026:03:04:27 +0000] "PATCH /api/config?restart=false HTTP/1.1" 200 4588 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}, @{Timestamp=10/6/2026 10:04:29 PM; Message=ACCESS: 192.168.1.162 - - [07/Oct/2026:03:04:28 +0000] "DELETE /api/auth HTTP/1.1" 204 558 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}, @{Timestamp=10/6/2026 10:04:33 PM; Message=ACCESS: 192.168.1.162 - - [07/Oct/2026:03:04:28 +0000] "POST /api/auth HTTP/1.1" 200 808 - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6; Priority=}}
+NextID : 4
+Pid : 389
File : /var/log/pihole/webserver.log
```
@@ -1214,9 +1217,9 @@ Get-PiHoleLogDnsmasq -PiHoleServer $PiHoleServer -Password $Password
```
-Log : {@{Timestamp=10/1/2026 8:28:22 AM; Message=started, version pi-hole-v2.93 cachesize 10000; Priority=}, @{Timestamp=10/1/2026 8:28:22 AM; Message=DNS service limited to local subnets; Priority=}, @{Timestamp=10/1/2026 8:28:22 AM; Message=compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n IDN2 DHCP DHCPv6 Lua TFTP no-conntrack ipset no-nftset auth DNSSEC loop-detect inotify dumpfile; Priority=}, @{Timestamp=10/1/2026 8:28:22 AM; Message=using nameserver 8.8.8.8#53; Priority=}…}
-NextID : 69
-Pid : 388
+Log : {@{Timestamp=10/6/2026 9:56:22 PM; Message=started, version pi-hole-v2.93 cachesize 10000; Priority=}, @{Timestamp=10/6/2026 9:56:22 PM; Message=DNS service limited to local subnets; Priority=}, @{Timestamp=10/6/2026 9:56:22 PM; Message=compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n IDN2 DHCP DHCPv6 Lua TFTP no-conntrack ipset no-nftset auth DNSSEC loop-detect inotify dumpfile; Priority=}, @{Timestamp=10/6/2026 9:56:22 PM; Message=using nameserver 8.8.8.8#53; Priority=}…}
+NextID : 21
+Pid : 389
File : /var/log/pihole/pihole.log
```
@@ -1228,9 +1231,9 @@ Get-PiHoleLogFtl -PiHoleServer $PiHoleServer -Password $Password
```
-Log : {@{Timestamp=10/1/2026 8:54:42 AM; Message=Wrote config file:; Priority=INFO}, @{Timestamp=10/1/2026 8:54:42 AM; Message= - 167 total entries; Priority=INFO}, @{Timestamp=10/1/2026 8:54:42 AM; Message= - 157 entries are default; Priority=INFO}, @{Timestamp=10/1/2026 8:54:42 AM; Message= - 10 entries are modified; Priority=INFO}…}
-NextID : 797
-Pid : 388
+Log : {@{Timestamp=10/6/2026 9:56:21 PM; Message=PID of FTL process: 389; Priority=INFO}, @{Timestamp=10/6/2026 9:56:21 PM; Message=listening on 0.0.0.0 port 53; Priority=INFO}, @{Timestamp=10/6/2026 9:56:21 PM; Message=listening on :: port 53; Priority=INFO}, @{Timestamp=10/6/2026 9:56:21 PM; Message=Database version is 22; Priority=INFO}…}
+NextID : 109
+Pid : 389
File : /var/log/pihole/FTL.log
```
@@ -1250,6 +1253,19 @@ RootFolder : C:\Users\mmadeja\AppData\Local\Temp\PiHoleShellDocsExample
FileSizeKB : 25
```
+### Import-PiHoleTeleporter
+
+_Prompts for confirmation by default since it can overwrite your whole configuration - pass -Confirm:$false to skip the prompt, or -WhatIf for a dry run. Omitting every item switch (as here, Group is just one example) imports everything in the archive instead of only the selected items._
+
+```powershell
+Import-PiHoleTeleporter -PiHoleServer $PiHoleServer -Password $Password -FilePath "C:\Backups\pihole-backup.zip" -Group
+```
+
+```
+
+Processed : {etc/pihole/gravity.db->group}
+```
+
### Get-PiHoleHistory
```powershell
@@ -1258,31 +1274,31 @@ Get-PiHoleHistory -PiHoleServer $PiHoleServer -Password $Password
```
-Timestamp : 9/30/2026 3:15:00 PM
+Timestamp : 10/5/2026 10:15:00 PM
Total : 0
Cached : 0
Blocked : 0
Forwarded : 0
-Timestamp : 9/30/2026 3:25:00 PM
+Timestamp : 10/5/2026 10:25:00 PM
Total : 0
Cached : 0
Blocked : 0
Forwarded : 0
-Timestamp : 9/30/2026 3:35:00 PM
+Timestamp : 10/5/2026 10:35:00 PM
Total : 0
Cached : 0
Blocked : 0
Forwarded : 0
-Timestamp : 9/30/2026 3:45:00 PM
+Timestamp : 10/5/2026 10:45:00 PM
Total : 0
Cached : 0
Blocked : 0
Forwarded : 0
-Timestamp : 9/30/2026 3:55:00 PM
+Timestamp : 10/5/2026 10:55:00 PM
Total : 0
Cached : 0
Blocked : 0
@@ -1299,20 +1315,20 @@ Get-PiHoleHistoryClient -PiHoleServer $PiHoleServer -Password $Password
```
-Timestamp : 9/30/2026 3:15:00 PM
-Clients : {@{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
+Timestamp : 10/5/2026 10:15:00 PM
+Clients : {@{IP=127.0.0.1; Name=localhost; Count=0}, @{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
-Timestamp : 9/30/2026 3:25:00 PM
-Clients : {@{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
+Timestamp : 10/5/2026 10:25:00 PM
+Clients : {@{IP=127.0.0.1; Name=localhost; Count=0}, @{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
-Timestamp : 9/30/2026 3:35:00 PM
-Clients : {@{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
+Timestamp : 10/5/2026 10:35:00 PM
+Clients : {@{IP=127.0.0.1; Name=localhost; Count=0}, @{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
-Timestamp : 9/30/2026 3:45:00 PM
-Clients : {@{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
+Timestamp : 10/5/2026 10:45:00 PM
+Clients : {@{IP=127.0.0.1; Name=localhost; Count=0}, @{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
-Timestamp : 9/30/2026 3:55:00 PM
-Clients : {@{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
+Timestamp : 10/5/2026 10:55:00 PM
+Clients : {@{IP=127.0.0.1; Name=localhost; Count=0}, @{IP=192.168.1.162; Name=; Count=0}, @{IP=others; Name=; Count=0}}
_(showing 5 of 145 results)_
```
@@ -1327,37 +1343,37 @@ Get-PiHoleHistoryDatabase -PiHoleServer $PiHoleServer -Password $Password
```
-Timestamp : 10/1/2026 9:00:00 AM
-Total : 42
-Cached : 5
-Blocked : 10
-Forwarded : 27
+Timestamp : 10/6/2026 3:00:00 PM
+Total : 1
+Cached : 1
+Blocked : 0
+Forwarded : 0
-Timestamp : 10/1/2026 10:00:00 AM
-Total : 3
-Cached : 3
+Timestamp : 10/6/2026 4:00:00 PM
+Total : 1
+Cached : 1
Blocked : 0
Forwarded : 0
-Timestamp : 10/1/2026 11:00:00 AM
-Total : 3
-Cached : 3
+Timestamp : 10/6/2026 5:00:00 PM
+Total : 1
+Cached : 1
Blocked : 0
Forwarded : 0
-Timestamp : 10/1/2026 12:00:00 PM
+Timestamp : 10/6/2026 6:00:00 PM
Total : 1
Cached : 1
Blocked : 0
Forwarded : 0
-Timestamp : 10/1/2026 1:00:00 PM
+Timestamp : 10/6/2026 7:00:00 PM
Total : 1
Cached : 1
Blocked : 0
Forwarded : 0
-_(showing 5 of 7 results)_
+_(showing 5 of 10 results)_
```
### Get-PiHoleHistoryDatabaseClient
@@ -1370,22 +1386,22 @@ Get-PiHoleHistoryDatabaseClient -PiHoleServer $PiHoleServer -Password $Password
```
-Timestamp : 10/1/2026 3:00:00 PM
-Clients : @{ClientId=3; Count=1}
+Timestamp : 10/6/2026 10:00:00 PM
+Clients : {@{ClientId=5; Count=1}, @{ClientId=3; Count=1}}
-Timestamp : 10/1/2026 2:00:00 PM
+Timestamp : 10/6/2026 9:50:00 PM
Clients : @{ClientId=3; Count=1}
-Timestamp : 10/1/2026 1:00:00 PM
+Timestamp : 10/6/2026 9:40:00 PM
Clients : @{ClientId=3; Count=1}
-Timestamp : 10/1/2026 12:00:00 PM
+Timestamp : 10/6/2026 9:00:00 PM
Clients : @{ClientId=3; Count=1}
-Timestamp : 10/1/2026 11:00:00 AM
+Timestamp : 10/6/2026 8:00:00 PM
Clients : @{ClientId=3; Count=1}
-_(showing 5 of 7 results)_
+_(showing 5 of 10 results)_
```
### Get-PiHoleNetworkGateway
@@ -1481,7 +1497,7 @@ ProtoDown : False
Address : 00:00:00:00:00:00
Broadcast : 00:00:00:00:00:00
Stats : @{RxBytes=; TxBytes=; Bits=64}
-Addresses : {@{Family=inet; Scope=host; Flags=permanent; Prefixlen=8; Address=127.0.0.1; AddressType=loopback; Local=127.0.0.1; LocalType=loopback; Label=lo; Prefered=4294967295; Valid=4294967295; Cstamp=1790649663.02; Tstamp=1790649663.02}, @{Family=inet6; Scope=host; Flags=permanent; Prefixlen=128; Address=::1; AddressType=loopback; Prefered=4294967295; Valid=4294967295; Cstamp=1790649663.02; Tstamp=1790649663.02}}
+Addresses : {@{Family=inet; Scope=host; Flags=permanent; Prefixlen=8; Address=127.0.0.1; AddressType=loopback; Local=127.0.0.1; LocalType=loopback; Label=lo; Prefered=4294967295; Valid=4294967295; Cstamp=1790957600.02; Tstamp=1790957600.02}, @{Family=inet6; Scope=host; Flags=permanent; Prefixlen=128; Address=::1; AddressType=loopback; Prefered=4294967295; Valid=4294967295; Cstamp=1790957600.02; Tstamp=1790957600.02}}
Name : wlan0
Speed :
@@ -1494,7 +1510,7 @@ Address : b8:27:eb:11:a4:d5
Broadcast : ff:ff:ff:ff:ff:ff
PermAddress : b8:27:eb:11:a4:d5
Stats : @{RxBytes=; TxBytes=; Bits=64}
-Addresses : {@{Family=inet; Scope=universe; Flags=; Prefixlen=24; Address=192.168.1.248; AddressType=private; Local=192.168.1.248; LocalType=private; Broadcast=192.168.1.255; BroadcastType=private; Label=wlan0; Prefered=63266; Valid=63266; Cstamp=1790649687.41; Tstamp=1790862827.1}, @{Family=inet6; Scope=link; Flags=permanent; Prefixlen=64; Address=fe80::ba27:ebff:fe11:a4d5; AddressType=link-local (LL); Prefered=4294967295; Valid=4294967295; Cstamp=1790649682.83; Tstamp=1790649682.83}}
+Addresses : {@{Family=inet; Scope=universe; Flags=; Prefixlen=24; Address=192.168.1.248; AddressType=private; Local=192.168.1.248; LocalType=private; Broadcast=192.168.1.255; BroadcastType=private; Label=wlan0; Prefered=62449; Valid=62449; Cstamp=1790957620.44; Tstamp=1791318773.93}, @{Family=inet6; Scope=link; Flags=permanent; Prefixlen=64; Address=fe80::ba27:ebff:fe11:a4d5; AddressType=link-local (LL); Prefered=4294967295; Valid=4294967295; Cstamp=1790957619.8; Tstamp=1790957619.8}}
```
### Get-PiHoleNetworkDevice
@@ -1510,20 +1526,20 @@ Get-PiHoleNetworkDevice -PiHoleServer $PiHoleServer -Password $Password
Id : 2
HwAddr : ip-127.0.0.1
Interface : lo
-FirstSeen : 10/1/2026 9:03:33 AM
-LastQuery : 10/1/2026 3:00:00 PM
-NumQueries : 13
+FirstSeen : 10/4/2026 2:31:10 PM
+LastQuery : 10/6/2026 10:06:14 PM
+NumQueries : 82
MacVendor :
-Ips : @{Ip=127.0.0.1; Name=localhost; LastSeen=10/1/2026 3:19:00 PM; NameUpdated=10/1/2026 3:19:00 PM}
+Ips : @{Ip=127.0.0.1; Name=localhost; LastSeen=10/6/2026 10:12:00 PM; NameUpdated=10/6/2026 10:12:00 PM}
Id : 1
HwAddr : 74:56:3c:bb:f4:0b
Interface : wlan0
-FirstSeen : 10/1/2026 9:03:32 AM
-LastQuery : 10/1/2026 9:03:33 AM
-NumQueries : 39
+FirstSeen : 10/4/2026 2:31:09 PM
+LastQuery : 10/6/2026 10:03:16 PM
+NumQueries : 318
MacVendor : Giga-Byte Technology Co.,Ltd.
-Ips : @{Ip=192.168.1.162; Name=; LastSeen=10/1/2026 3:19:00 PM; NameUpdated=12/31/1969 6:00:00 PM}
+Ips : @{Ip=192.168.1.162; Name=; LastSeen=10/6/2026 10:12:00 PM; NameUpdated=12/31/1969 6:00:00 PM}
```
### Remove-PiHoleNetworkDevice
@@ -1576,8 +1592,8 @@ Get-PiHoleAuthStatus -PiHoleServer $PiHoleServer -Password $Password
Valid : True
Totp : False
-Sid : 8sHZ0t+C5DwLRgIcKIM7/g=
-Csrf : 1xmNq2FNUPFo7bnCRoUzIQ=
+Sid : +dfslUHafhrdo0TwRT5nxQ=
+Csrf : Em6pqkbJ6cuWxjQw7EtUFw=
Validity : 1800
Message : correct password
```
@@ -1597,8 +1613,8 @@ Algorithm : SHA1
Digits : 6
Period : 30
Offset : 0
-Secret : XP4YEGF2S75KCDBN7BSW37AEA65AQZBQ
-Codes : {414882, 273855, 226959, 897753…}
+Secret : EG7DLOTZKTQWIRWBFR2JJLS5Q3BYNUN3
+Codes : {201435, 619358, 736784, 226002…}
```
### Get-PiHoleCurrentAuthSession
@@ -1610,13 +1626,41 @@ Get-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Password $Password
```
Id : 0
+CurrentSession : False
+Valid : True
+TlsLogin : True
+TlsMixed : False
+LoginAt : 10/6/2026 9:44:13 PM
+LastActive : 10/6/2026 9:44:17 PM
+ValidUntil : 10/6/2026 10:14:17 PM
+RemoteAddress : 192.168.1.162
+UserAgent : Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6
+XForwardedFor :
+App : True
+Cli : False
+
+Id : 1
+CurrentSession : False
+Valid : True
+TlsLogin : True
+TlsMixed : False
+LoginAt : 10/6/2026 9:44:59 PM
+LastActive : 10/6/2026 9:44:59 PM
+ValidUntil : 10/6/2026 10:14:59 PM
+RemoteAddress : 192.168.1.162
+UserAgent : Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6
+XForwardedFor :
+App : True
+Cli : False
+
+Id : 2
CurrentSession : True
Valid : True
TlsLogin : True
TlsMixed : False
-LoginAt : 10/1/2026 3:10:59 PM
-LastActive : 10/1/2026 3:11:03 PM
-ValidUntil : 10/1/2026 3:41:03 PM
+LoginAt : 10/6/2026 10:03:33 PM
+LastActive : 10/6/2026 10:03:37 PM
+ValidUntil : 10/6/2026 10:33:37 PM
RemoteAddress : 192.168.1.162
UserAgent : Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.26200; en-US) PowerShell/7.6.6
XForwardedFor :
@@ -1629,13 +1673,13 @@ Cli : False
_Deletes a session by its ID (as shown by Get-PiHoleCurrentAuthSession), not the caller's own session._
```powershell
-Remove-PiHoleAuthSession -PiHoleServer $PiHoleServer -Password $Password -Id 0
+Remove-PiHoleAuthSession -PiHoleServer $PiHoleServer -Password $Password -Id 2
```
```
-Id : 0
+Id : 2
Status : Removed
```
diff --git a/tests/Teleporter/Import-PiHoleTeleporter.Integration.Tests.ps1 b/tests/Teleporter/Import-PiHoleTeleporter.Integration.Tests.ps1
new file mode 100644
index 0000000..8bc9636
--- /dev/null
+++ b/tests/Teleporter/Import-PiHoleTeleporter.Integration.Tests.ps1
@@ -0,0 +1,83 @@
+# Requires -Module Pester
+#
+# Integration tests that call a REAL Pi-hole server. Configure tests/IntegrationConfig.local.ps1
+# (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically
+# if that file is missing.
+#
+# NOTE: The "real import" test below selectively restores only the groups table from a backup
+# taken of the server's own current state, so it's a no-op restore rather than a destructive
+# change - safe to run repeatedly. Confirmed by hand that Pi-hole briefly reloads internally
+# right after any import (a transient 401/connection error on the very next call), so this file
+# settles with a short delay afterward rather than asserting anything about server state
+# immediately following an import.
+
+$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1')
+
+Describe 'Import-PiHoleTeleporter (Integration)' -Tag 'Integration' {
+ BeforeAll {
+ Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force
+
+ $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1'
+ if (Test-Path $configPath) {
+ . $configPath
+ $script:PiHoleServer = $PiHoleServer
+ $script:PiHoleToken = $PiHoleToken
+ $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl
+
+ $script:TestFolder = Join-Path ([System.IO.Path]::GetTempPath()) 'PiHoleShellPesterTeleporterImport'
+ if (Test-Path $script:TestFolder) {
+ Remove-Item -Path $script:TestFolder -Recurse -Force
+ }
+ New-Item -ItemType Directory -Path $script:TestFolder | Out-Null
+
+ # -ErrorAction Stop so a real failure here fails BeforeAll loudly instead of leaving
+ # $script:BackupFilePath silently $null (Get-PiHoleTeleporterDownload traps its own
+ # errors internally and just writes a non-terminating error otherwise).
+ $backup = Get-PiHoleTeleporterDownload -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -FolderPath $script:TestFolder -FileName 'import-fixture' -ErrorAction Stop
+ $script:BackupFilePath = $backup.FilePath
+ }
+ }
+
+ AfterAll {
+ if ($script:TestFolder -and (Test-Path $script:TestFolder)) {
+ Remove-Item -Path $script:TestFolder -Recurse -Force
+ }
+ }
+
+ It 'imports a selected item from a real backup and returns a formatted object' -Skip:(-not $script:ConfigAvailable) {
+ $result = Import-PiHoleTeleporter -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -FilePath $script:BackupFilePath -Group -Confirm:$false
+ $result | Format-List | Out-String | Write-Host
+
+ $result | Should -Not -BeNullOrEmpty
+ $result.Processed | Should -Not -BeNullOrEmpty
+ $result.Processed | Should -Match 'group'
+
+ # Pi-hole reloads internally right after an import - give it a moment before the next test.
+ Start-Sleep -Seconds 5
+ }
+
+ It 'does not import anything when -WhatIf is set' -Skip:(-not $script:ConfigAvailable) {
+ { Import-PiHoleTeleporter -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -FilePath $script:BackupFilePath -Group -WhatIf } | Should -Not -Throw
+ }
+
+ It 'errors when the file does not exist' -Skip:(-not $script:ConfigAvailable) {
+ $result = Import-PiHoleTeleporter -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -FilePath (Join-Path $script:TestFolder 'does-not-exist.zip') -Confirm:$false -ErrorVariable errOut -ErrorAction SilentlyContinue
+
+ $errOut | Should -Not -BeNullOrEmpty
+ }
+
+ It 'errors when the uploaded file is not a valid ZIP archive' -Skip:(-not $script:ConfigAvailable) {
+ $badFile = Join-Path $script:TestFolder 'not-a-zip.zip'
+ 'this is not a zip file' | Set-Content -Path $badFile
+
+ $result = Import-PiHoleTeleporter -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -FilePath $badFile -Confirm:$false -ErrorVariable errOut -ErrorAction SilentlyContinue
+
+ $errOut | Should -Not -BeNullOrEmpty
+ }
+
+ It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) {
+ $result = Import-PiHoleTeleporter -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -FilePath $script:BackupFilePath -Confirm:$false -ErrorVariable errOut -ErrorAction SilentlyContinue
+
+ $errOut | Should -Not -BeNullOrEmpty
+ }
+}
diff --git a/tools/Update-ExampleOutput.ps1 b/tools/Update-ExampleOutput.ps1
index 865609d..35cb802 100644
--- a/tools/Update-ExampleOutput.ps1
+++ b/tools/Update-ExampleOutput.ps1
@@ -261,6 +261,18 @@ Add-Example -Category Config -FunctionName 'Get-PiHoleTeleporterDownload' `
-Invocation 'Get-PiHoleTeleporterDownload -PiHoleServer $PiHoleServer -Password $Password -FolderPath "C:\Backups" -FileName "pihole-backup"' `
-Note 'FolderPath/FileName are yours to choose; the captured output below used a scratch temp folder for this run instead of C:\Backups.' `
-Result (Get-PiHoleTeleporterDownload -PiHoleServer $PiHoleServer -Password $PiHoleToken -IgnoreSsl $PiHoleIgnoreSsl -FolderPath $teleporterFolder -FileName 'pihole-backup')
+
+# Restoring the archive just downloaded above is a no-op (it's a backup of the server's own
+# current state), so this is safe to run for real rather than needing a throwaway target.
+Add-Example -Category Config -FunctionName 'Import-PiHoleTeleporter' `
+ -Invocation 'Import-PiHoleTeleporter -PiHoleServer $PiHoleServer -Password $Password -FilePath "C:\Backups\pihole-backup.zip" -Group' `
+ -Note 'Prompts for confirmation by default since it can overwrite your whole configuration - pass -Confirm:$false to skip the prompt, or -WhatIf for a dry run. Omitting every item switch (as here, Group is just one example) imports everything in the archive instead of only the selected items.' `
+ -Result (Import-PiHoleTeleporter -PiHoleServer $PiHoleServer -Password $PiHoleToken -IgnoreSsl $PiHoleIgnoreSsl -FilePath (Join-Path $teleporterFolder 'pihole-backup.zip') -Group -Confirm:$false)
+
+# Pi-hole reloads internally right after any import, briefly refusing connections - confirmed by
+# hand against a real server. Without this, the very next example's own request can fail.
+Start-Sleep -Seconds 5
+
Remove-Item $teleporterFolder -Recurse -Force
#endregion