<!--
{
  "documentType" : "article",
  "framework" : "Network",
  "identifier" : "/documentation/Network/indicating-the-source-of-network-activity",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Indicating the source of network activity"
}
-->

# Indicating the source of network activity

Control whether the App Privacy Report attributes network traffic to the app or to the user.

## Discussion

In iOS and iPadOS 15 or later, users can view an App Privacy Report that includes the network domains that apps on the device have recently accessed. The report differentiates between network connections that the user initiates and those that the app initiates.

By default, the system attributes all connections — except those that your app makes using <doc://com.apple.documentation/documentation/SafariServices/SFSafariViewController> or <doc://com.apple.documentation/documentation/AuthenticationServices/ASWebAuthenticationSession> — to the app. However, for network connections that meet certain criteria, you can tell the system to attribute the connection to the user. The API you use to control attribution depends on how you make the network connection.

To learn how to examine all the data your app contributes to the privacy report, see [Inspecting app activity data](/documentation/Network/inspecting-app-activity-data).

### Determine the appropriate attribution

All connections, other than those that use <doc://com.apple.documentation/documentation/SafariServices/SFSafariViewController> or <doc://com.apple.documentation/documentation/AuthenticationServices/ASWebAuthenticationSession>, are classified by default as *app-initiated*. User-initiated network connections are the exception. Network connections to third-party domains can only be classified as *user-initiated* if they meet all of the following criteria:

- User-directed — Network connections to domains that occur only when a user affirmatively chooses to engage with content in your app. For a connection to qualify as user-directed, the user must be provided with a meaningful choice of whether to interact with the content.
- Non-primary functionality — The app’s features must be functional without this particular network connection.

If you don’t categorize your app’s traffic using the APIs, all network connections are classified as app-initiated.

For example, the following connections should retain the app-initiated attribution:

- A podcast app that automatically chooses and downloads podcasts based on the user’s interests. While the loaded content isn’t core to the app, the user has no control over it.
- An app that transmits analytics and other user data for use in improving the app. The access is core to the app’s functionality, and the user has no control over it.
- A maps app that loads and presents content from a review service — for example, for hotels or restaurants — when the user taps on a location pin. The action is core to the app’s functionality, and the user didn’t explicitly request the information.

In contrast, you can attribute these connections to the user:

- Links to user-generated content in a social media app, like when a user clicks or taps a news feed link. The user chooses the link, and the particular link isn’t part of the app’s primary functionality.
- Messages in an email app. The user creates and configures the email account, and no particular email or email account is central to the app’s functionality.
- Pages loaded by a web browser. The user chooses the web sites to visit, and no particular web site is specific to the app’s functionality. Note that connections made by the browser that the user doesn’t choose, like sending analytics data or retrieving user configuration information, should retain app attribution.

To reclassify an access as user-initiated, use API at the same layer of the protocol stack that you use to make the connection.

### Attribute URL Loading System connections

To mark a connection as user-initiated when using the <doc://com.apple.documentation/documentation/Foundation/url-loading-system>, create an explicit <doc://com.apple.documentation/documentation/Foundation/URLRequest> and set its <doc://com.apple.documentation/documentation/Foundation/URLRequest/attribution-swift.property> property to <doc://com.apple.documentation/documentation/Foundation/NSURLRequest/Attribution-swift.enum/user> before calling one of the <doc://com.apple.documentation/documentation/Foundation/URLSession> methods that takes a request, like <doc://com.apple.documentation/documentation/Foundation/URLSession/data(for:delegate:)>:

```swift
import Foundation

let url = URL(string: "https://example.com")!
var request = URLRequest(url: url)
request.attribution = .user

let (data, response) = try await URLSession.shared.data(for: request)
```

The <doc://com.apple.documentation/documentation/Foundation/NSURLRequest> and <doc://com.apple.documentation/documentation/Foundation/NSMutableURLRequest> classes also have a comparable property. Use this kind of parameterized request for other high level link types as well, as the next few sections describe.

### Attribute WebKit loads

A <doc://com.apple.documentation/documentation/WebKit> network access that you initiate with a URL request using the <doc://com.apple.documentation/documentation/webkit/wkwebview/load(_:)> method honors the attribution parameter that you set on the <doc://com.apple.documentation/documentation/Foundation/URLRequest> instance, just like the previous section describes for a <doc://com.apple.documentation/documentation/Foundation/URLSession> access. If you want to set an attribution when you use WebKit to load an HTML string, data, or a file URL, use one of the corresponding load methods that takes a request. For example, you can load an HTML string with attribution using the <doc://com.apple.documentation/documentation/WebKit/WKWebView/loadSimulatedRequest(_:responseHTML:)> method, relying on the `request` defined in the previous section:

```swift
import WebKit

let webView = WKWebView()
let html = "<html><body><h1>Hello, world!</h1></body></html>"

webView.loadSimulatedRequest(request, responseHTML: html)
```

Alternatively, you can load a data version of the same content using the <doc://com.apple.documentation/documentation/WebKit/WKWebView/loadSimulatedRequest(_:response:responseData:)> method:

```swift
let data = Data(html.utf8)
let response = URLResponse(
    url: url,
    mimeType: "text/HTML",
    expectedContentLength: data.count,
    textEncodingName: "UTF-8")

webView.loadSimulatedRequest(request, response: response, responseData: data)
```

To load a file called `index.html` from your main bundle’s `resources` directory with user attribution, use the <doc://com.apple.documentation/documentation/WebKit/WKWebView/loadFileRequest(_:allowingReadAccessTo:)> method:

```swift
let fileURL = Bundle.main.url(
    forResource: "index",
    withExtension: "html",
    subdirectory: "resources")!

var fileRequest = URLRequest(url: fileURL)
fileRequest.attribution = .user

webView.loadFileRequest(
    fileRequest,
    allowingReadAccessTo: fileURL.deletingLastPathComponent())
```

These load methods — as opposed to their non-request counterparts like <doc://com.apple.documentation/documentation/WebKit/WKWebView/loadHTMLString(_:baseURL:)> and <doc://com.apple.documentation/documentation/WebKit/WKWebView/loadFileRequest(_:allowingReadAccessTo:)> — also enable the user to browse backward and forward among the corresponding pages.

### Attribute LinkPresentation metadata fetches

To load link presentation metadata with attribution, use the <doc://com.apple.documentation/documentation/LinkPresentation/LPMetadataProvider> fetch method that takes a request. Specifically, use the <doc://com.apple.documentation/documentation/LinkPresentation/LPMetadataProvider/startFetchingMetadata(for:completionHandler:)-9e6s8> method — again, relying on the user-attributed `request` value that you defined earlier:

```swift
import LinkPresentation

let metadataProvider = LPMetadataProvider()
let metadata = try await metadataProvider.startFetchingMetadata(for: request)
```

### Attribute Network framework connections

To control attribution when using the [`Network`](/documentation/Network) framework, set the [`attribution`](/documentation/Network/NWParameters/attribution-swift.property) property of an [`NWParameters`](/documentation/Network/NWParameters) instance to [`NWParameters.Attribution.user`](/documentation/Network/NWParameters/Attribution-swift.enum/user), and use that to create a connection:

```swift
import Network

let parameters = NWParameters()
parameters.attribution = .user
let endpoint = NWEndpoint.url(url)
let connection = NWConnection(to: endpoint, using: parameters)
```

Alternatively, you can work with an [`nw_parameters_t`](/documentation/Network/nw_parameters_t) instance, and set the attribution to [`nw_parameters_attribution_t.user`](/documentation/Network/nw_parameters_attribution_t/user) with a call to the [`nw_parameters_set_attribution(_:_:)`](/documentation/Network/nw_parameters_set_attribution(_:_:)) function:

```swift
let parameters = nw_parameters_create()
nw_parameters_set_attribution(parameters, .user)
let endpoint = nw_endpoint_create_url("https://example.com")
let connection = nw_connection_create(endpoint, parameters)
```

### Attribute connections made with sockets

To control attribution when working with sockets, import the `ne_socket.h` header file, and use the `ne_socket_set_attribution` function to set the value `NE_SOCKET_ATTRIBUTION_USER` on a socket:

```objc
#include <sys/socket.h>
#include <networkext/ne_socket.h>

int tcpSocket = socket(PF_INET, SOCK_STREAM, 0);
if (ne_socket_set_attribution(tcpSocket, NE_SOCKET_ATTRIBUTION_USER) != 0) {
    // Handle error.
}
```

If you use custom DNS resolution, also call `ne_socket_set_domains()` function to associate the resolved domain name (as well as any resolved `CNAME`) with the socket:

```objc
const char *domains[] = { "resolved.example.com" };
if (ne_socket_set_domains(tcpSocket, domains, 1) != 0) {
    // Handle error.
}
```

This gives the system an opportunity to evaluate whether the resolved domain has been identified as potentially collecting information across apps and sites. After performing any additional configuration, use the socket to create a connection:

```objc
const struct sockaddr *address = <#Some address#>;
int connectResult = connect(tcpSocket, address, address->sa_len);
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)