Enabling the Inspection of Web Content in Apps

Web Inspector is a powerful tool that allows you to debug the layout of web pages, step through JavaScript, read messages logged to the console, and more. In Safari on macOS, you can use Web Inspector to inspect web pages, extensions, and service workers. iOS and iPadOS allow inspection of the same content as macOS, with the addition of Home Screen web apps.

Web content and JavaScript is used for various purposes in apps, from providing UI from a webpage to enabling apps to be scriptable. Previously, Web Inspector supported inspecting developer-provisioned apps built directly from Xcode for local development, meaning developers could debug this content so long as the app is installed for development. However, released versions of apps had no way to inspect dynamic web content or scripts, leaving developers and users to have to resort to more complicated workflows to get information that would otherwise be made available by Web Inspector. Now, this same functionality is available through an API on WKWebView and JSContext.

How do I enable inspection?

Across all platforms supporting WKWebView or JSContext, a new property is available called isInspectable (inspectable in Objective-C). It defaults to false, and you can set it to true to opt-in to content being inspectable. This decision is made for each individual WKWebView and JSContext to prevent unintentionally making it enabled for a view or context you don’t intend to be inspectable. So, for example, to make a WKWebView inspectable, you would:

Swift
let webConfiguration = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.isInspectable = true
Objective-C
WKWebViewConfiguration *webConfiguration = [WKWebViewConfiguration new];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfiguration];
webView.inspectable = YES;

For JSContext, matching API is available, with the addition of C API for developers using JSGlobalContextRef:

Swift
let jsContext = JSContext()
jsContext?.isInspectable = true
Objective-C
JSContext *jsContext = [JSContext new];
jsContext.inspectable = YES;
C
JSGlobalContextRef jsContextRef = JSGlobalContextCreate(NULL);
JSGlobalContextSetInspectable(jsContextRef, true);

The inspectable property can be changed at any point during the lifetime of your WKWebView or JSContext. Disabling inspection while Web Inspector actively inspects the content will automatically close Web Inspector, and no further information about the content will be available.

Once you’ve enabled inspection for your app, you can inspect it from Safari’s Develop menu in the submenu for either your current computer or an attached device. For iOS and iPadOS, you must also have enabled Web Inspector in the Settings app under Safari > Advanced > Web Inspector. You do not need to enable Web Inspector for simulators; it is always enabled. Learn more about enabling Web Inspector…

Develop Menu > Patrick's iPhone > Example App

When should I consider making content inspectable?

A common situation in which you may want the content of WKWebView to be inspectable is in an in-app web browser. The browser shows ordinary web content that would be inspectable when loaded in Safari. It can be beneficial both for the app developer, as well as web authors, to be able to inspect content in these views, as the size of the view may not match that of Safari’s, or the app developer may be injecting script into the view to provide integration with their app.

Web content is often dynamic, delivered by a server—not in the app—and easily changed over time. Unfortunately, not all issues can or will get debugged by folks with access to a developer-provisioned copy of your app.

JSContext can also enable scripting in an app whereby the customer provides the scripts to augment the app. Without the ability for a release version of your app to adopt inspectability, your customers may have no way to debug the scripts they have written. It makes it harder for customers to use this functionality of your app.

Provide readable names for inspectable JSContexts

Unlike WKWebView, which automatically gets a name based on the page currently loaded in the view, every JSContext with inspectable enabled will be listed as JSContext in Safari’s Develop menu. We recommend providing a unique, human-readable name for each inspectable JSContext to make it easier for you and your customers to determine what the JSContext represents. For example, if your app runs different pieces of JavaScript on behalf of the user, you should give each JSContext a name based on what runs inside the context.

API is available to set the user-visible name of a JSContext:

Swift
let jsContext = JSContext()
jsContext?.name = "Context name"
Objective-C
JSContext *jsContext = [JSContext new];
jsContext.name = @"Context name";
C
JSGlobalContextRef jsContextRef = JSGlobalContextCreate(NULL);
`JSGlobalContextSetName`(jsContextRef, JSStringCreateWithUTF8CString("Context name"));

Working with older versions of macOS and iOS

For apps linked against an SDK before macOS 13.3 and iOS 16.4 WKWebViews and JSContexts will continue to follow the previous behavior of always being inspectable when built for debugging from Xcode.

Apps that support older versions of macOS and iOS while linked against the most recent SDK will not get the previous behavior of all content being inspectable in debug builds to avoid confusion about what will and will not be inspectable by customers. Apps targeting older OS versions but linking against the new SDK can use this new API conditionally on OS versions that support it. To conditionally guard usage of the API:

Swift
if #available(macOS 13.3, iOS 16.4, tvOS 16.4, *) {
    webView.isInspectable = true
}
Objective-C
if (@available(macOS 13.3, iOS 16.4, tvOS 16.4, *))
    webView.inspectable = YES;

You can learn more about guarding usage of new API on developer.apple.com.

Feedback

As you explore this new API, please help us by providing feedback if you encounter problems. For issues using this new API, please file feedback from your Mac, iPhone, or iPad. Feedback Assistant will collect the information needed to help us understand what’s happening. For any issues you may experience with Web Inspector itself once inspecting your app’s content, please file a bug on bugs.webkit.org.

Also, we love hearing from you. You can find us on Mastodon at @patrickangle@hachyderm.io, @jensimmons@front-end.social, and @jondavis@mastodon.social.

Note: Learn more about Web Inspector from the Web Inspector Reference documentation.