Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

To capture a website rendered in a Swift app, load it in a WKWebView and call WebKit’s asynchronous takeSnapshot(with:completionHandler:). Configure a WKSnapshotConfiguration when you need a specific rectangle, output width, or screen-update behavior. The result is a platform-native image: UIImage on iOS-family platforms and NSImage on macOS.

What the Swift screenshot API actually captures

WKWebView renders web content; its snapshot method turns the rendered view into an image. Apple describes takeSnapshot(with:completionHandler:) as generating a platform-native image from the web view’s contents asynchronously. It is therefore different from taking a screenshot of the entire device display: browser chrome and unrelated app UI are not included.

WebKit can load a page from a server, local file, or HTML string. Resources referenced by the initial request are loaded as part of that web content. See Apple’s WKWebView documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Basic UIKit implementation

Add WebKit to the file that owns your view controller, create a web view, load the URL, and wait for navigation to finish before requesting the image.

#1 Best Overall
Apple iPhone 14, 128GB, Midnight - Unlocked (Renewed)
  • This phone is unlocked and compatible with any carrier of choice on GSM and CDMA networks (e.g. AT&T, T-Mobile, Sprint, Verizon, US Cellular, Cricket, Metro, Tracfone, Mint Mobile, etc.).
  • Please check with your carrier to verify compatibility.
  • The device does not come with headphones or a SIM card. It does include a generic (Mfi certified) charging cable.
  • Tested for battery health and guaranteed to have a minimum battery capacity of 80%.
import UIKit
import WebKit

final class WebScreenshotViewController: UIViewController, WKNavigationDelegate {
    private let webView = WKWebView(frame: .zero)

    override func viewDidLoad() {
        super.viewDidLoad()

        webView.navigationDelegate = self
        webView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(webView)
        NSLayoutConstraint.activate([
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])

        guard let url = URL(string: "https://example.com") else { return }
        webView.load(URLRequest(url: url))
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let configuration = WKSnapshotConfiguration()
        configuration.rect = webView.bounds
        configuration.afterScreenUpdates = true

        webView.takeSnapshot(with: configuration) { [weak self] image, error in
            guard let self else { return }
            if let error {
                print("Snapshot failed: (error.localizedDescription)")
                return
            }
            guard let image else {
                print("WebKit returned no image")
                return
            }
            UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.saveError), nil)
        }
    }

    @objc private func saveError(_ image: UIImage,
                                 didFinishSavingWithError error: Error?,
                                 contextInfo: UnsafeRawPointer) {
        if let error { print("Save failed: (error.localizedDescription)") }
    }
}

The completion handler may contain an error or no image, so production code should handle both. The operation is asynchronous; do not expect an image immediately after calling the method.

Saving or displaying the result

On iOS, iPadOS, Mac Catalyst, and visionOS, the completion value is a UIImage. You can assign it to an image view, write PNG or JPEG data, share it, or save it to Photos (with the appropriate Photos usage description and authorization). For example:

guard let pngData = image.pngData() else { return }
try? pngData.write(to: FileManager.default.temporaryDirectory
    .appendingPathComponent("website.png"))

Check the actual image before converting it; conversion can fail for unusual or invalid image representations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Capture a selected region and control output size

WKSnapshotConfiguration accepts a rectangle in the web view’s coordinate system, a snapshot width in points, and an afterScreenUpdates flag. Use the rectangle to capture only a card, header, or other visible region:

Rank #2
Sale
Apple iPhone 16, 128GB, Pink - Unlocked (Renewed)
  • 6.1" Super Retina XDR OLED, HDR10, Dolby Vision, 1000nits (typ), 2000nits (HBM), 2556x1179px at 460ppi, 3561mAh Battery
  • 128GB 8GB RAM, Apple A18 (3nm), Hexa-core (2x4.04 GHz + 4x2.20 GHz), Apple GPU 5-core, 16‑core Neural Engine
  • Rear camera: 48MP, f/1.6, wide + 12MP, f/2.2, ultrawide, Front Camera: 12MP, f/1.9, wide, iOS 18, upgradable to iOS 18.5
  • 4G LTE: 1/2/3/4/5/7/8/12/13/14/17/18/19/20/25/26/28/29/30/32/34/38/39/40/41/42/48/53/66/71, 5G: n1/2/3/5/7/8/12/14/20/25/26/28/29/30/38/40/41/48/53/66/70/71/75/76/77/78/79 - Dual eSIM
  • Unlocked for freedom to choose your carrier. Compatible with both GSM & CDMA networks. The phone is unlocked to work with all GSM Carriers & CDMA Carriers Including AT&T, T-Mobile, Verizon, Sprint., Etc.
let configuration = WKSnapshotConfiguration()
configuration.rect = webView.convert(targetView.bounds, from: targetView)
configuration.snapshotWidth = 1_200
configuration.afterScreenUpdates = true

webView.takeSnapshot(with: configuration) { image, error in
    // Handle image and error here.
}

Ensure the rectangle lies within the web view’s coordinate space and has a positive size. A larger snapshot width can improve detail but also increases memory and processing requirements.

SwiftUI: wrap WKWebView, keep the snapshot in WebKit

SwiftUI does not replace the WebKit API. Wrap WKWebView with UIViewRepresentable (or NSViewRepresentable on macOS), retain the web-view reference, and trigger the same asynchronous call from a coordinator, observable model, or explicit user action.

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let url: URL
    let onCreated: (WKWebView) -> Void

    func makeUIView(context: Context) -> WKWebView {
        let view = WKWebView()
        view.load(URLRequest(url: url))
        onCreated(view)
        return view
    }

    func updateUIView(_ view: WKWebView, context: Context) {}
}

struct ContentView: View {
    @State private var webView: WKWebView?
    @State private var screenshot: UIImage?

    var body: some View {
        VStack {
            if let screenshot { Image(uiImage: screenshot).resizable().scaledToFit() }
            WebView(url: URL(string: "https://example.com")!) { webView in
                self.webView = webView
            }
            Button("Capture") {
                guard let webView else { return }
                let configuration = WKSnapshotConfiguration()
                configuration.rect = webView.bounds
                configuration.afterScreenUpdates = true
                webView.takeSnapshot(with: configuration) { image, error in
                    guard error == nil else { return }
                    DispatchQueue.main.async { self.screenshot = image }
                }
            }
        }
    }
}

In a real app, avoid creating a new web view every SwiftUI update; keep ownership in a model or wrapper coordinator. The sample shows the API shape, not a complete navigation-state architecture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Async/await form

Supported modern SDKs provide an async overload. The platform image type still differs by target:

Rank #3
Apple iPhone 15, 128GB, Black - Unlocked (Renewed)
  • 6.1inch Super Retina XDR display. Aluminum with color-infused glass back. Ring/Silent switch
  • Dynamic Island. A magical way to interact with iPhone. A16 Bionic chip with 5-core GPU
  • Advanced dual-camera system. 48MP Main | Ultra Wide. Super-high-resolution photos (24MP and 48MP). Next-generation portraits with Focus and Depth Control. 4X optical zoom range
  • Emergency SOS via satellite. Crash Detection. Roadside Assistance via satellite
  • Up to 26 hours video playback. USB C, Supports USB 2. Face ID
let configuration = WKSnapshotConfiguration()
configuration.rect = webView.bounds
configuration.afterScreenUpdates = true

 do {
    let image = try await webView.takeSnapshot(configuration: configuration)
    // UIImage on iOS-family platforms; NSImage on macOS.
} catch {
    print(error.localizedDescription)
}

Call this from an async context, such as a task started after navigation has completed. The method is not a guarantee that every late network resource or animation has finished.

Waiting for a page that is really ready

didFinish indicates that navigation finished, but pages may continue loading images, fonts, JavaScript data, advertisements, or animations. Choose a readiness strategy appropriate to your page:

  • Have page JavaScript set a known flag or add a marker element, then wait for it with evaluateJavaScript before capturing.
  • Use a short, bounded delay only when the page is predictable; long arbitrary delays make captures slow and still do not prove readiness.
  • Disable or pause animations in injected CSS when a deterministic frame matters.
  • Capture on the main thread and keep the web view alive until the completion handler runs.

afterScreenUpdates = true asks WebKit to incorporate pending screen updates. Apple does not describe it as waiting for every asynchronous resource, network request, or animation.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Full-page screenshots: an important limitation

The configuration’s rectangle is defined in the web view’s coordinate system. The cited Apple documentation does not make a universal promise that takeSnapshot captures an arbitrarily long page beyond the view’s configured or displayed region. If you need the entire document, verify behavior for your target OS, content, and layout rather than assuming a full-page result.

Rank #4
Apple iPhone 13, 128GB, Midnight - Unlocked (Renewed)
  • This pre-owned product is not Apple certified, but has been professionally inspected, tested and cleaned by Amazon-qualified suppliers.
  • There will be no visible cosmetic imperfections when held at an arm’s length.
  • This product is eligible for a replacement or refund within 90 days of receipt if you are not satisfied.
  • Product may come in generic Box.

For a document output rather than a raster image, use WebKit’s separate asynchronous PDF API, pdf(configuration:), with WKPDFConfiguration. It returns PDF data and is the appropriate choice when pagination and text-oriented output matter. See Apple’s PDF documentation.

macOS differences

On macOS, WebKit uses an AppKit view and the snapshot result is an NSImage, not a UIImage. Use NSViewRepresentable in SwiftUI and AppKit image representations when writing PNG or TIFF data. Keep platform-specific image handling behind conditional compilation if one codebase targets both macOS and iOS.

Troubleshooting

The completion handler returns an error or nil image

  • Confirm the web view has not been deallocated and that the call is made after it has been attached and laid out.
  • Log the supplied error instead of replacing it with a generic message.
  • Check that the rectangle is nonzero and in the web view’s coordinate system.
  • Retry only for transient page or rendering failures; repeated retries can hide a deterministic layout problem.

The image is blank or incomplete

  • Wait for a meaningful DOM marker rather than immediately capturing after load.
  • Verify the URL, network access, redirects, authentication, and content-security behavior.
  • Increase the web view’s size or set an explicit snapshot width if the capture region is unexpectedly small.
  • Remember that a screen-update flag does not wait for every asynchronous asset.

Cookies, consent dialogs, or login screens appear

Those are part of the page state presented to the web view. Configure WKWebsiteDataStore, cookies, and authentication deliberately; never bypass access controls without authorization.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Saving to Photos fails

Request Photos permission and add the required usage-description key. For server-side or automated output, write image data to your app’s storage instead of Photos.

Best Value
Apple iPhone 16e, 128GB, Black - Unlocked (Renewed)
  • 6.1" Super Retina XDR OLED, HDR10, 800 nits (HBM), 1200 nits (peak), 2532x1170px at 460ppi, 4005mAh Battery
  • 8GB RAM, Apple A18 6-core CPU (2 performance + 4 efficiency cores), Apple GPU 4-core, 16‑core Neural Engine
  • Rear camera: 48MP, f/1.6, wide, Front Camera: 12MP, f/1.9, wide, iOS 18.3.1, upgradable to iOS 18.5
  • Connectivity: Global 4G LTE, Sub-6 GHz 5G, LTE, Wi-Fi 6, Bluetooth 5.3, NFC, USB-C, Wireless Charging (7.5W). (does not have mmWave 5G or MagSafe or physical SIM card) - Dual eSIM Only
  • Unlocked for freedom to choose your carrier. Compatible with both GSM & CDMA networks. The phone is unlocked to work with all GSM Carriers & CDMA Carriers Including AT&T, T-Mobile, Verizon, Straight Talk., Etc.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, memory, and reliability

  • Reuse a web view when capturing several pages, but clear or isolate website data when sessions must not affect one another.
  • Large rectangles and high snapshot widths consume more memory. Capture only what you need and release image data promptly.
  • Do not block the main thread while encoding PNG or JPEG; move expensive post-processing off the UI path.
  • Record the URL, viewport, rectangle, SDK, and error when a capture fails so you can reproduce layout-specific issues.
  • For untrusted pages, treat returned content as untrusted data and keep navigation and JavaScript policies explicit.

Or skip the browser setup

If you need a URL-to-image service instead of embedding WebKit, ScreenshotNeo makes one GET request and returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.

ScreenshotNeo also provides an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf tools. Its 63 options include full-page capture with lazy-image loading, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Common screenshot-API parameter names also work.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for response formats and options. Equivalent clients:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 shots per month with no card. Paid plans are Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start.

API and PDF decision checklist

Need Use Result
Rendered content inside your Swift app WKWebView.takeSnapshot Platform-native image asynchronously
Specific visible or configured region WKSnapshotConfiguration.rect Image of the selected coordinate-space rectangle
Raster output at a chosen width snapshotWidth Image sized according to the configured width
Paginated document WKWebView.pdf(configuration:) PDF data
Automated URL capture without app WebKit ScreenshotNeo API PNG, JPEG, WebP, or PDF response

Frequently Asked Questions

Does WKWebView screenshot the Safari browser chrome?

No. The snapshot is generated from the WKWebView’s rendered contents, so Safari or unrelated app interface is not part of the image.

Can I call takeSnapshot synchronously?

No. The completion-handler API and async overload both complete asynchronously and can report an error.

What image class should shared Swift code expect?

Use UIImage on iOS, iPadOS, Mac Catalyst, and visionOS; use NSImage on macOS.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When should I choose PDF instead of a screenshot?

Choose WebKit’s pdf(configuration:) when the required deliverable is PDF data with document-style pagination rather than a raster image.

Quick Recap

Bestseller No. 1
Apple iPhone 14, 128GB, Midnight - Unlocked (Renewed)
Apple iPhone 14, 128GB, Midnight - Unlocked (Renewed)
Please check with your carrier to verify compatibility.; Tested for battery health and guaranteed to have a minimum battery capacity of 80%.
$300.00
Bestseller No. 3
Apple iPhone 15, 128GB, Black - Unlocked (Renewed)
Apple iPhone 15, 128GB, Black - Unlocked (Renewed)
Dynamic Island. A magical way to interact with iPhone. A16 Bionic chip with 5-core GPU; Emergency SOS via satellite. Crash Detection. Roadside Assistance via satellite
$409.00
Bestseller No. 4
Apple iPhone 13, 128GB, Midnight - Unlocked (Renewed)
Apple iPhone 13, 128GB, Midnight - Unlocked (Renewed)
There will be no visible cosmetic imperfections when held at an arm’s length.; Product may come in generic Box.
$262.00

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.