A class you use to configure and control a URL filter.
The system performs URL filtering on your behalf according to your configuration and URL data set.
The system filters all URL requests initiated with the <doc://com.apple.documentation/documentation/WebKit>
and <doc://com.apple.documentation/documentation/Foundation/URLSession> APIs.
During URL filtering, the system performs sub-URL generation to
enumurate all possible sub-URLs for the URL in question. For example, the URL
https://www.sub1.example.com/a/b/c?id=123#fragment
parses into the following sub-URLs:
* `example.com`
* `example.com/`
* `example.com/a`
* `example.com/a/`
* `example.com/a/b`
* `example.com/a/b/`
* `example.com/a/b/c`
* `example.com/a/b/c/`
* `example.com/a/b/c/?id=123`
* `example.com/a/b/c/?id=123#fragment`
* `example.com/a/b/c?id=123`
* `example.com/a/b/c?id=123#fragment`
* `example.com:443`
* `example.com:443/`
* `example.com:443/a`
* `example.com:443/a/`
* `example.com:443/a/b`
* `example.com:443/a/b/`
* `example.com:443/a/b/c`
* `example.com:443/a/b/c/`
* `example.com:443/a/b/c/?id=123`
* `example.com:443/a/b/c/?id=123#fragment`
* `example.com:443/a/b/c?id=123`
* `example.com:443/a/b/c?id=123#fragment`
* `sub1.example.com`
* `sub1.example.com/`
* `sub1.example.com/a`
* `sub1.example.com/a/`
* `sub1.example.com/a/b`
* `sub1.example.com/a/b/`
* `sub1.example.com/a/b/c`
* `sub1.example.com/a/b/c/`
* `sub1.example.com/a/b/c/?id=123`
* `sub1.example.com/a/b/c/?id=123#fragment`
* `sub1.example.com/a/b/c?id=123`
* `sub1.example.com/a/b/c?id=123#fragment`
* `sub1.example.com:443`
* `sub1.example.com:443/`
* `sub1.example.com:443/a`
* `sub1.example.com:443/a/`
* `sub1.example.com:443/a/b`
* `sub1.example.com:443/a/b/`
* `sub1.example.com:443/a/b/c`
* `sub1.example.com:443/a/b/c/`
* `sub1.example.com:443/a/b/c/?id=123`
* `sub1.example.com:443/a/b/c/?id=123#fragment`
* `sub1.example.com:443/a/b/c?id=123`
* `sub1.example.com:443/a/b/c?id=123#fragment`
The manager matches each of these sub-URLs against your Bloom filter and then against the PIR URL database if there's a Bloom filter match.
The verdict indicates if the app should block the requested URL.
Note that the manager Punycodes the requested URL before parsing.
Because of this, be sure to Punycode your own URL dataset before constructing your Bloom filter and PIR database.
Neither the Bloom filter nor PIR supports wildcards or regular expressions.
For a more flexible URL matching solution, use the ``urlParsingConfiguration`` property to select the URL components -- the scheme, domain, path, query, fragment) -- to include in the parsing results.
You can also use the ``urlParsingRegularExpression`` property to implement custom parsing.
Instances of this class are thread-safe.
### Configuring the PIR server
URL filtering requires that your app's information property list contain a top-level `PIRConfiguration` dictionary.
The dictionary contains two keys, as follows:
- term `serviceURL`: (Required) The URL of the PIR server. This is equivalent to the ``pirServerURL`` property.
- term `issuerURL`: (Optional) The URL of the Privacy Pass Issuer. This is equivalent to the ``pirPrivacyPassIssuerURL`` property. If absent, the `issuerURL` defaults to the value of `serviceURL`.
An example `PIRConfiguration` dictionary follows:
```xml
<key>PIRConfiguration</key>
<dict>
<key>serviceURL</key>
<string>https://pir.example.com</string>
<key>issuerURL</key>
<string>https://issuer.example.com</string>
</dict>
```
Members (34)
get · iOS 26.0+
pirServerURL
TypeScript
get pirServerURL(): (string) | null
Swift declaration
var pirServerURL: URL? { get }
URL containing the domain name of the PIR server. URL filter App implementation must set up a PIR server
(hosting a URL dataset) reachable at the specified PIR server URL. For all HTTP requests made using any of
the Apple networking frameworks, NetworkExtension system validates the requested URL via the PIR
technology with the specified PIR server before the HTTP requests can be sent.
To set up the PIR server for URL filtering, it must contain a PIR use case with the following name format:
"<App bundle identifier>.url.filtering".
Your URL data set contains URLs you want to block. All URLs in the data set must be already puny-coded
before construction of the PIR database.
get · iOS 27.0+
reportFormat
TypeScript
get reportFormat(): NEURLFilterManager_ReportFormat
Swift declaration
var reportFormat: NEURLFilterManager.ReportFormat { get set }
The format the manager uses to send blocked URL reports.
Use the values in the ``ReportFormat`` enumeration to specify the format to use.
By default, the manager uses the ``ReportFormat/json`` format.
### Handling JSON results
When you specify the ``ReportFormat/json`` format, your endpoint receives data in JSON as a simple array of strings.
The structure of this data is like the following:
```json
[
"example.com",
"example2.com",
"example3.com"
]
```
### Handling Protobuf results
When you specify the ``ReportFormat/protobuf`` format, your endpoint receives the Protocol Buffers wire format with manual encoding for a repeated string field.
Each URL entry follows this binary structure:
- term Field Tag: 1 byte (`0x0A` = field number 1, wire type 2 for length-delimited).
- term String Length: A variable-length integer (varint) encoding the byte length of the URL string.
- term String Data: UTF-8 encoded URL bytes.
For strings under 128 bytes, the length is a single byte.
For longer strings, the protocol uses varint encoding, where each byte has the MSB set (`0x80`) except the final byte.
The following example shows the encoding of the URL `https://example.com`:
```
Example encoding for URL "https://example.com":
[0x0A] [0x13] [h][t][t][p][s][:][/][/][e][x][a][m][p][l][e][.][c][o][m]
^tag ^len=19 ^------------ 19 bytes of UTF-8 string data ------------^
```
set · iOS 27.0+
reportFormat
TypeScript
set reportFormat(value: NEURLFilterManager_ReportFormat)
Swift declaration
var reportFormat: NEURLFilterManager.ReportFormat { get set }
The format the manager uses to send blocked URL reports.
Use the values in the ``ReportFormat`` enumeration to specify the format to use.
By default, the manager uses the ``ReportFormat/json`` format.
### Handling JSON results
When you specify the ``ReportFormat/json`` format, your endpoint receives data in JSON as a simple array of strings.
The structure of this data is like the following:
```json
[
"example.com",
"example2.com",
"example3.com"
]
```
### Handling Protobuf results
When you specify the ``ReportFormat/protobuf`` format, your endpoint receives the Protocol Buffers wire format with manual encoding for a repeated string field.
Each URL entry follows this binary structure:
- term Field Tag: 1 byte (`0x0A` = field number 1, wire type 2 for length-delimited).
- term String Length: A variable-length integer (varint) encoding the byte length of the URL string.
- term String Data: UTF-8 encoded URL bytes.
For strings under 128 bytes, the length is a single byte.
For longer strings, the protocol uses varint encoding, where each byte has the MSB set (`0x80`) except the final byte.
The following example shows the encoding of the URL `https://example.com`:
```
Example encoding for URL "https://example.com":
[0x0A] [0x13] [h][t][t][p][s][:][/][/][e][x][a][m][p][l][e][.][c][o][m]
^tag ^len=19 ^------------ 19 bytes of UTF-8 string data ------------^
```
method · iOS 26.0+
resetPIRCache
TypeScript
resetPIRCache(): Promise<void>
Swift declaration
func resetPIRCache() async throws
The function resets the PIR on-device cache. The PIR system on device caches previous PIR queries and responses to minimize
exchanges with the PIR server. When there is a dataset change on the PIR server, a reset of the on-device cache may be needed
to avoid using stale cache entries.
- throws
- Error : returns optional error to indicate the fail reason.
get · iOS 27.0+
reportEndpoint
TypeScript
get reportEndpoint(): (string) | null
Swift declaration
var reportEndpoint: String? { get set }
The endpoint that the filter manager sends blocked URL reports to.
When configured, the manager sends reports of blocked URLs to the specified endpoint on the PIR server URL.
In other words, for a PIR server at `https://pir.example.com/` and an endpoint of `reports`, the manager sends reports to `https://pir.example.com/reports`.
The manager sends reports periodically, as determined by the ``reportInterval`` property, using the format specified by ``reportFormat``.
Each report is an HTTPS POST request, containing a list of blocked URLs accumulated during the last reporting period.
The system authenticates and sends reports over the same OHTTP relay as the PIR traffic.
Due to the system's schedulding mechanism, your reporting system should allow slight deviations between the scheduled time and the actual performance of the task.
Reporting is available only on supervised devices.
If you set this property on a non-supervised device, the manager will save the configuration but won't send any reports.
To disable reporting, set this property to `nil`.
set · iOS 27.0+
reportEndpoint
TypeScript
set reportEndpoint(value: (string) | null)
Swift declaration
var reportEndpoint: String? { get set }
The endpoint that the filter manager sends blocked URL reports to.
When configured, the manager sends reports of blocked URLs to the specified endpoint on the PIR server URL.
In other words, for a PIR server at `https://pir.example.com/` and an endpoint of `reports`, the manager sends reports to `https://pir.example.com/reports`.
The manager sends reports periodically, as determined by the ``reportInterval`` property, using the format specified by ``reportFormat``.
Each report is an HTTPS POST request, containing a list of blocked URLs accumulated during the last reporting period.
The system authenticates and sends reports over the same OHTTP relay as the PIR traffic.
Due to the system's schedulding mechanism, your reporting system should allow slight deviations between the scheduled time and the actual performance of the task.
Reporting is available only on supervised devices.
If you set this property on a non-supervised device, the manager will save the configuration but won't send any reports.
To disable reporting, set this property to `nil`.
get · iOS 27.0+
reportInterval
TypeScript
get reportInterval(): number
Swift declaration
var reportInterval: TimeInterval { get set }
The time interval (in seconds) at which the system sends reports of blocked URLs.
This value defaults to `86400`, equal to one day. The minimum allowed interval is `3600` (one hour).
set · iOS 27.0+
reportInterval
TypeScript
set reportInterval(value: number)
Swift declaration
var reportInterval: TimeInterval { get set }
The time interval (in seconds) at which the system sends reports of blocked URLs.
This value defaults to `86400`, equal to one day. The minimum allowed interval is `3600` (one hour).
Set an URL filter configuration with the required PIR server attributes as well as App extension information.
- Parameters:
- pirServerURL: PIR server URL. The URL must contain only the domain name of the PIR server.
- pirPrivacyPassIssuer: PIR Privacy Pass Issuer URL. The URL must contain only the domain name of the Privacy Pass Issuer.
If nil, PIR server URL will be used as Privacy Pass Issuer URL.
- pirAuthenticationToken: An HTTP bearer token that authenticates the person using your app. The system uses this token to
attest that it is a valid user when requesting anonymous authentication tokens.
- controlProviderBundleIdentifier: Bundle Identifier of the NEURLFilterControlProvider app extension.
- throws
- Error : returns optional error to indicate the fail reason.
get · iOS 26.0+
shouldFailClosed
TypeScript
get shouldFailClosed(): boolean
Swift declaration
var shouldFailClosed: Bool { get set }
If YES, URLs will be blocked if the filter is enabled but failed to make any filtering decision (e.g. communication failure
with the PIR server). If NO, URLs will be allowed if the filter is enabled but failed to make any filtering decision. Default is NO.
set · iOS 26.0+
shouldFailClosed
TypeScript
set shouldFailClosed(value: boolean)
Swift declaration
var shouldFailClosed: Bool { get set }
If YES, URLs will be blocked if the filter is enabled but failed to make any filtering decision (e.g. communication failure
with the PIR server). If NO, URLs will be allowed if the filter is enabled but failed to make any filtering decision. Default is NO.
method · iOS 26.0+
saveToPreferences
TypeScript
saveToPreferences(): Promise<void>
Swift declaration
func saveToPreferences() async throws
This function saves the URL filter configuration in the caller's URL filter preferences. If the URL filter is enabled, it will become active.
- throws
- Error : returns optional error to indicate the fail reason.
method · iOS 26.0+
handleConfigChange
TypeScript
handleConfigChange(): SDKHandle
Swift declaration
func handleConfigChange() -> any AsyncSequence<Bool, Never>
This method observes the NEURLFilterConfigurationDidChange notification and returns an AsyncSequence that yields true every time the notification is posted.
Use this method to watch for configuration change and react to it.
- Parameters:
- Bool: true will be returned at every configuration change.
method · iOS 26.0+
handleStatusChange
TypeScript
handleStatusChange(): SDKHandle
Swift declaration
func handleStatusChange() -> any AsyncSequence<NEURLFilterManager.Status, Never>
This method observes the NEURLFilterStatusDidChange notification and returns an AsyncSequence that yields the new status every time the notification is posted.
Use this method to watch for status change and react to it.
- Parameters:
- Status: the latest status will be returned at every status change.
get · iOS 26.0+
appBundleIdentifier
TypeScript
get appBundleIdentifier(): (string) | null
Swift declaration
var appBundleIdentifier: String? { get }
Bundle Identifier of the URL filter app.
get · iOS 26.0+
lastDisconnectError
TypeScript
get lastDisconnectError(): Promise<(NEURLFilterManager_Error) | null>
Swift declaration
var lastDisconnectError: NEURLFilterManager.Error? { get async }
Retrieve the most recent error that caused the URL Filter to stop. The returned error will be one of the NEURLFilterManager.Error.
method · iOS 26.0+
loadFromPreferences
TypeScript
loadFromPreferences(): Promise<void>
Swift declaration
func loadFromPreferences() async throws
This function loads the current URL filter configuration from the caller's URL filter preferences.
- throws
- Error : returns optional error to indicate the fail reason.
get · iOS 26.0+
localizedDescription
TypeScript
get localizedDescription(): (_Foundation_LocalizedStringResource) | null
Swift declaration
var localizedDescription: LocalizedStringResource?
A string containing a description of the URL filter.
set · iOS 26.0+
localizedDescription
TypeScript
set localizedDescription(value: (_Foundation_LocalizedStringResource) | null)
Swift declaration
var localizedDescription: LocalizedStringResource?
A string containing a description of the URL filter.
method · iOS 26.0+
refreshPIRParameters
TypeScript
refreshPIRParameters(): Promise<void>
Swift declaration
func refreshPIRParameters() async throws
This function refetches PIR parameters from the server. In most cases, an explicit refetch is not necessary since PIR system on device
refetches PIR parameters from server periodically to stay up-to-update with the server side. However, in case of a significant server
database change, PIR parameters may change. In this case, an explicit trigger of a refetch may be desirable to make the new set of PIR
parameters effective immediately.
Things that can cause PIR parameters to change:
re-processing the dataset
change of shard count
change of encryption parameters
change of per shard cuckoo hash table size (note: per shard entry count can change, while the cuckoo hash table stays fixed size)
change of cuckoo hashing parameters
- throws
- Error : returns optional error to indicate the fail reason.
method · iOS 26.0+
removeFromPreferences
TypeScript
removeFromPreferences(): Promise<void>
Swift declaration
func removeFromPreferences() async throws
This function removes the URL filter configuration from the caller's URL filter preferences. If the URL filter is enabled, the URL filter becomes disabled.
- throws
- Error : returns optional error to indicate the fail reason.
get · iOS 26.0+
pirAuthenticationToken
TypeScript
get pirAuthenticationToken(): (string) | null
Swift declaration
var pirAuthenticationToken: String? { get }
PIR per-user authentication token string. An HTTP bearer token that authenticates the person using your app. The system uses this token to
attest that it is a valid user when requesting anonymous authentication tokens.
get · iOS 26.0+
prefilterFetchInterval
TypeScript
get prefilterFetchInterval(): number
Swift declaration
var prefilterFetchInterval: TimeInterval { get set }
The time interval at which the NEURLFilterControlProvider app extension will run. Defaults to every 86,400 seconds (1 day).
Minimum allowed is 2700 seconds (45 minutes). NEURLFilterControlProvider implementation will be able to download prefilter
Bloom filter data onto device periodically at the specified interval. Due to scheduling mechanism on the system, implementation
should allow slight deviation between the scheduled time and the actual execution time of the task.
set · iOS 26.0+
prefilterFetchInterval
TypeScript
set prefilterFetchInterval(value: number)
Swift declaration
var prefilterFetchInterval: TimeInterval { get set }
The time interval at which the NEURLFilterControlProvider app extension will run. Defaults to every 86,400 seconds (1 day).
Minimum allowed is 2700 seconds (45 minutes). NEURLFilterControlProvider implementation will be able to download prefilter
Bloom filter data onto device periodically at the specified interval. Due to scheduling mechanism on the system, implementation
should allow slight deviation between the scheduled time and the actual execution time of the task.
get · iOS 26.0+
pirPrivacyPassIssuerURL
TypeScript
get pirPrivacyPassIssuerURL(): (string) | null
Swift declaration
var pirPrivacyPassIssuerURL: URL? { get }
URL containing the domain name of Privacy Pass Issuer.
get · iOS 27.0+
urlParsingConfiguration
TypeScript
get urlParsingConfiguration(): NEURLFilterManager_ParsingConfiguration
Swift declaration
var urlParsingConfiguration: NEURLFilterManager.ParsingConfiguration { get set }
A property to configure the filter's parser behavior.
Use this property to control which URL components to exclude, and to customize parsing behavior during sub-URL enumeration.
This determines how the filter parses URLs which sub-URLs it generates for matching against the filter data set.
For any excluded component -- domain, path, query, or fragment -- the filter substitutes `"%*"` in place as a placeholder.
By contrast, if you strip the domain or `www` subdomain, they're removed entirely without a placeholder, since URL matching doesn't typically require them.
As an example, consider the URL `https://www.example.com/a/b/c?id=123#fragment` and a configuration set as follows:
```swift
var config = manager.urlParsingConfiguration
config.excludeScheme = true
config.domain.stripWWW = true
config.path.excluded = true
manager.urlParsingConfiguration = config
```
The parsing result is `example.com/%*?id=123#fragment`, where `"%*"` acts as the placeholder for the excluded path component.
The presence of a placeholder indicates the original URL contained that component, but the parsing configuration excluded it.
If the filter manager sets ``urlParsingRegularExpression``, this configuration has no effect.
set · iOS 27.0+
urlParsingConfiguration
TypeScript
set urlParsingConfiguration(value: NEURLFilterManager_ParsingConfiguration)
Swift declaration
var urlParsingConfiguration: NEURLFilterManager.ParsingConfiguration { get set }
A property to configure the filter's parser behavior.
Use this property to control which URL components to exclude, and to customize parsing behavior during sub-URL enumeration.
This determines how the filter parses URLs which sub-URLs it generates for matching against the filter data set.
For any excluded component -- domain, path, query, or fragment -- the filter substitutes `"%*"` in place as a placeholder.
By contrast, if you strip the domain or `www` subdomain, they're removed entirely without a placeholder, since URL matching doesn't typically require them.
As an example, consider the URL `https://www.example.com/a/b/c?id=123#fragment` and a configuration set as follows:
```swift
var config = manager.urlParsingConfiguration
config.excludeScheme = true
config.domain.stripWWW = true
config.path.excluded = true
manager.urlParsingConfiguration = config
```
The parsing result is `example.com/%*?id=123#fragment`, where `"%*"` acts as the placeholder for the excluded path component.
The presence of a placeholder indicates the original URL contained that component, but the parsing configuration excluded it.
If the filter manager sets ``urlParsingRegularExpression``, this configuration has no effect.
get · iOS 27.0+
urlParsingRegularExpression
TypeScript
get urlParsingRegularExpression(): (string) | null
Swift declaration
var urlParsingRegularExpression: String? { get }
A regular expression used for advanced URL parsing.
This property is read-only.
To set a regular expression for use in parsing, call ``setURLParsingRegularExpression(_:)``, which validates the pattern.
Setting a regular expression allows you to perform custom URL parsing patterns beyond the standard parsing options.
The filter uses the regular expression to parse the URL before matching against the specified data set.
URL parsing with a regular expression is case insensitive.
Sets a regular expression for use in URL parsing.
Setting a regular expression allows you to perform custom URL parsing patterns beyond the standard parsing options.
The filter uses the regular expression to parse the URL before matching against the specified data set.
Calling this method validates the `pattern` you provide for the regular expression.
In your regular expression, use the standard name captured group syntax.
For example, `"https?://(?<host>[^/]+)"` captures the domain by using the group name `host`.
You can use whatever custom labels you want for group names, but they are limited to ASCII alphanumeric characters.
The result is a single string that uses the space character for a delimiter between each name-value pair, such as:
```
<group-1-name>=<group-1-value> <group-2-name>=<group-2-value> <group-3-name>=...
```
Providing a `pattern` without a named capture group throws an error.
If you provide a regular expression that uses other types of captured groups, only the named captured groups appear in the result.
Setting a regular expression causes the ``urlParsingConfiguration`` parameter to have no effect.
You can read the current value of the regular expression with the ``urlParsingRegularExpression`` property.
URL parsing with a regular expression is case insensitive.
get · iOS 26.0+
controlProviderBundleIdentifier
TypeScript
get controlProviderBundleIdentifier(): (string) | null
Swift declaration
var controlProviderBundleIdentifier: String? { get }
Bundle Identifier of the NEURLFilterControlProvider app extension.
get · iOS 26.0+
shared
TypeScript
static get shared(): NEURLFilterManager
Swift declaration
static var shared: NEURLFilterManager { get }
The singleton NEURLFilterManager object for the calling process.
get · iOS 26.0+
status
TypeScript
get status(): Promise<NEURLFilterManager_Status>
Swift declaration
var status: NEURLFilterManager.Status { get async }
Current status of the URL filter.
get · iOS 26.0+
isEnabled
TypeScript
get isEnabled(): boolean
Swift declaration
var isEnabled: Bool { get set }
Toggles the enabled status of the URL filter. If YES, the URL filter will start filtering URLs. If NO, the URL filter will cease URL filtering.
Defaults to NO.
set · iOS 26.0+
isEnabled
TypeScript
set isEnabled(value: boolean)
Swift declaration
var isEnabled: Bool { get set }
Toggles the enabled status of the URL filter. If YES, the URL filter will start filtering URLs. If NO, the URL filter will cease URL filtering.
Defaults to NO.