ScreenshotNeo

BlogHow-to

How to Embed Web Content With an SDK

Choose the right web view for your app, load a page safely, handle navigation, and know when an iframe or in-app browser is a better fit.

By the ScreenshotNeo team29 September 202612 min read

How to Embed Web Content With an SDK

To embed web content in an app, use the platform’s web view when the page belongs inside your app’s interface. Android provides WebView; Apple platforms provide WKWebView. If a user is simply following a link, Android Custom Tabs provide a browser-powered in-app browsing experience. If you mean embedding a site inside another website, that is an iframe, with different security and policy constraints.

There is no single cross-platform embedding SDK. Pick the component based on who controls the page, how much native integration it needs, whether it must work offline, and where navigation should go. This guide includes starter code, security boundaries, navigation patterns, iframe constraints, troubleshooting, and a way to capture screenshots of the finished page.

1. Choose the embedding model

First answer the literal question: How do I embed web content in my app? The short version is to put the platform web view in your layout and load a URL, a local asset, or generated HTML. The architectural choice is whether to use a view that your app controls or a browser experience that handles links.

Choose an embedded native view for integrated content, browser UI for link browsing, and an iframe for website-to-website embedding.
Choose an embedded native view for integrated content, browser UI for link browsing, and an iframe for website-to-website embedding.
Need Use Reason
A web screen integrated with native controls and layout Android WebView or Apple WKWebView The web content occupies a region of your app UI.
A user following a web link while staying in the app Android Custom Tabs It supplies a browser-powered browsing journey.
Static app-owned content that should work offline Platform web view plus local asset mechanism Assets ship with the app; updates require an app release.
A third-party page inside a web page HTML iframe, if both sites permit it The browser’s frame and security policies apply.

Use an embedded view for content that is part of the product experience, such as a feed, tutorial, agreement, mini-game, or account screen. Use browser UI when the user is browsing a destination and familiar browser behavior matters. Android explicitly distinguishes WebView, for controlled inline content, from Custom Tabs, for an in-app browser experience. Android: use web content within your app

Before implementation, decide which origins can load, whether links stay in the view, whether the page needs native capabilities, and whether content is remote or bundled. Those decisions affect security, navigation, and update behavior more than the choice of a convenience wrapper.

2. Android: add a WebView

Android’s WebView is a view that renders web pages as part of an Activity. It can load remote URLs, local files, and generated content, and it can run JavaScript. It does not include a browser address bar or full browser navigation controls by default. See the current Android WebView guide and check the Jetpack Webkit version used in your project.

Minimal layout and Activity code

Add internet permission for remote pages, place a WebView in the layout, then load the URL. This Kotlin example assumes a layout resource named activity_web.xml containing the WebView below.

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- res/layout/activity_web.xml -->
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

// WebActivity.kt
class WebActivity : AppCompatActivity() {
    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_web)
        webView = findViewById(R.id.webView)
        webView.webViewClient = WebViewClient()
        webView.loadUrl("https://example.com")
    }

    override fun onBackPressed() {
        if (::webView.isInitialized && webView.canGoBack()) {
            webView.goBack()
        } else {
            super.onBackPressed()
        }
    }
}

For new Jetpack Webkit integrations, Android recommends considering WebViewCompat.navigate instead of loadUrl; it offers improved history entry replacement, lifecycle callback tracking, and saved-state header support. Confirm availability and the library version in your app before using it. Navigation methods must be called on the UI thread. Android: WebViewCompat.navigate

WebView or Custom Tabs?

A WebView gives your app control over placement and interaction. You own loading states, navigation rules, back behavior, and any browser-like controls you choose to build. Custom Tabs are a better starting point when the feature is “open this link” rather than “show this web screen as part of our own interface.” They are powered by the user’s browser and provide more browsing functionality out of the box. Don’t build an address bar and navigation experience in a WebView unless that is genuinely part of your product.

3. Apple platforms: use WKWebView

WKWebView is Apple’s native view for interactive HTML, CSS, and JavaScript in an app UI. It can load a server URL, a local file, or an HTML string. Navigation and UI delegates let the app respond to navigation and web-driven UI events; WKWebViewConfiguration provides configuration points such as preferences, cookies, and custom URL schemes. Start with Apple’s WKWebView documentation.

import UIKit
import WebKit

final class WebViewController: UIViewController, WKNavigationDelegate {
    private var webView: WKWebView!

    override func loadView() {
        let configuration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: configuration)
        webView.navigationDelegate = self
        view = webView
    }

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

    func webView(_ webView: WKWebView,
                 decidePolicyFor navigationAction: WKNavigationAction,
                 decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // Add an explicit destination policy here if the app needs one.
        decisionHandler(.allow)
    }
}

This is a minimal view controller, not a complete browser. Add loading and error states, decide how back navigation works, and define a destination policy that fits your app. If an app handles only a known service, constrain navigation to expected destinations and route unrelated links to the appropriate external experience. Don’t assume a delegate policy can make arbitrary third-party content trustworthy.

4. Load bundled content and generated HTML

Remote pages are convenient when the content changes frequently, but they need connectivity and depend on the server. Bundled pages can work offline and do not consume network bandwidth to fetch those assets. Their tradeoff is deployment: changing bundled HTML, CSS, or JavaScript requires shipping an app update, and older app versions may show content that no longer matches the website.

On Android, prefer WebViewAssetLoader for in-app HTML assets. It serves local content through HTTP(S)-style URLs, which helps preserve normal web origin behavior. Follow the current Android local content guide to configure the asset loader and intercept requests. Avoid treating arbitrary file:// URLs as a drop-in substitute for a properly configured local origin.

For a small generated document, WKWebView can load an HTML string. Supply a base URL when relative links or assets need a defined origin:

let html = "<!doctype html><html><body><h1>Welcome</h1></body></html>"
webView.loadHTMLString(html, baseURL: URL(string: "https://app.example/"))

Generated HTML is still web content. Escape or encode values inserted into markup, keep untrusted strings out of script contexts, and avoid giving generated pages bridge access they do not need. For large or frequently updated documents, a controlled server page or bundled asset structure is easier to maintain than concatenating markup in application code.

5. Treat navigation and JavaScript bridges as security boundaries

A remote page is a separate trust domain. If you enable communication from page JavaScript to native code, the page may be able to invoke host capabilities. Expose only the smallest set of operations needed, and only to content whose origin and integrity you control. A bridge that can read files, use credentials, or trigger sensitive app actions should never be available to arbitrary destinations.

Navigation rules and JavaScript bridges define which web content can interact with native app capabilities.
Navigation rules and JavaScript bridges define which web content can interact with native app capabilities.
  • Define the allowed origins and schemes before loading content.
  • Inspect navigation and decide which destinations stay embedded, open elsewhere, or are blocked.
  • Do not enable JavaScript-to-native communication for pages that do not require it.
  • Keep authentication and secrets out of URLs and injected scripts.
  • Test redirects and links, not just the first page load.
  • Use supported local asset mechanisms so origin and same-origin assumptions remain clear.

Apple’s navigation delegates provide a place to handle or prevent navigation. Android’s WebView APIs likewise provide client callbacks and JavaScript interaction mechanisms. These controls require app-specific policy; accepting every destination by default is only suitable for a deliberately unrestricted browsing experience. Consult the platform documentation for the current API behavior.

6. Website embedding: iframe is a separate case

If you are embedding a page in another website, use an iframe only when the framed site allows it and the required capabilities work in that context. The host page and framed server can each impose security restrictions. A frame that refuses to load may be blocked by the target’s policy; changing CSS on the host page cannot override the other site’s response headers.

<iframe
  src="https://content.example/embedded"
  title="Embedded content"
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
  allow="fullscreen"
></iframe>

Use a meaningful title for accessibility, grant only necessary permissions, and size the frame responsively. Do not assume the parent page can read or control a cross-origin iframe’s DOM. Browser same-origin protections are intentional. Some embed platforms also provide a constrained iframe environment, so test the exact permissions and APIs your app depends on.

The W3C’s CSP Embedded Enforcement document is a Working Draft describing a mechanism for an embedder to propose restrictions that the framed page agrees to enforce. It is not a universal guarantee that arbitrary sites can be embedded or that all browsers support the mechanism. Check the target platform’s current documentation and test the frame in the actual host environment.

7. Test the rendered result and capture screenshots

Embedding bugs often appear only after JavaScript runs, a redirect occurs, a cookie prompt appears, or a narrow viewport changes the layout. Test representative states: initial load, slow network, offline or failed load, back navigation, external links, and the viewport sizes your app supports. Include a page with long content and one that changes after hydration or user input.

For manual review, use platform debugging tools and inspect the page in the actual app shell. For repeatable visual artifacts, capture the rendered URL or a specific page state. A screenshot is useful for documenting layout, comparing responsive states, and sharing a failure report; it does not replace testing the app’s navigation, accessibility, or native bridge behavior.

8. Or skip the browser setup

If your goal is to capture a website screenshot for review or documentation, rather than embed a live page in an app, ScreenshotNeo provides a website screenshot API and MCP server. A single GET request returns an image or PDF. See the API documentation for parameters and response details.

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

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. This captures a page for review; it does not embed interactive content into a native app.

Sign up for 1,000 free screenshots a month, with no card required.

9. Troubleshooting common failures

Symptom Likely cause Fix
Android view stays blank for a remote page Internet permission is missing, the URL is malformed, or the request failed. Check manifest permission, device connectivity, URL scheme, and WebView console/network errors. Show a visible error state.
Page loads, but JavaScript-driven content is absent The site depends on scripts, delayed requests, or a browser capability not available in the view. Inspect console errors and wait for the app’s real readiness condition. Enable only required capabilities and test on supported WebView versions.
Links unexpectedly leave the app No WebView client or navigation policy handles the destination. Set the appropriate client/delegate and explicitly decide which links remain embedded.
Back exits instead of returning to the previous page The app delegates back without checking web history. Check canGoBack() and call goBack() before leaving the screen.
Local assets cannot find scripts or styles Asset paths or origin assumptions differ from the bundled layout. Use Android WebViewAssetLoader or the platform’s supported local-file loading API; verify relative paths and base URL.
Iframe shows a refusal or blank area The framed site’s policy disallows framing, or its app requires unavailable permissions. Use the provider’s supported embed flow, check console and response headers, or open the destination separately.
Native bridge action is unavailable The bridge is not configured, the page origin differs, or the content loaded before setup. Verify configuration timing, origin rules, and platform support. Keep bridge calls optional and handle failure in the page.
Web page is slow or memory-heavy A web view runs a browser engine and page scripts may consume substantial resources. Profile page payload and scripts, avoid unnecessary simultaneous web views, and release views when screens are discarded.

10. Performance, reliability, and cost

A WebView adds a browser engine to an app that already uses native views, so its baseline memory cost is higher than ordinary Android views. Keep the number of live instances appropriate to the screen flow, avoid loading content before it is needed, and measure on target devices. A remote site also inherits network latency, server availability, redirects, and third-party script behavior. A local bundle avoids fetching its own assets and can work offline, but it becomes stale until an app update is installed.

Reliability comes from making loading outcomes explicit. Show progress while a page is loading, distinguish an HTTP or navigation failure from a legitimate empty page, give users a retry path, and avoid leaving a blank rectangle after timeout. Preserve only the navigation state that is useful; large serialized histories can create state-restoration problems. Check the current Android guidance for WebView saved-state limits and lifecycle behavior.

There is no universal SDK price to quote for platform web views: they are platform APIs. The engineering costs are implementation, content hosting, testing across OS and browser-engine versions, and maintenance of the web experience. A website iframe likewise has no single embedding price; access and restrictions depend on the service being framed. For screenshot capture, ScreenshotNeo’s stated plans are Free (1,000 per month), Starter ($5 / 3,000), Growth ($15 / 15,000), Pro ($39 / 60,000), Scale ($99 / 250,000), and Business ($249 / 1,000,000); annual billing gives two months free. Every feature is on every plan.

11. Implementation checklist

  1. Choose the platform component: WebView, Custom Tabs, WKWebView, or iframe.
  2. Decide whether content is remote, local, or generated, and document the update and offline behavior.
  3. Set a navigation policy for internal routes, redirects, and external destinations.
  4. Keep JavaScript-to-native access off unless required; restrict any bridge to trusted content.
  5. Implement loading, error, retry, back, and lifecycle behavior.
  6. Test real devices, slow or missing connectivity, responsive states, and long pages.
  7. For iframe use, verify that the framed service allows the intended embedding and permissions.
  8. Capture screenshots of representative rendered states when visual review is part of the release process.

FAQ

Is WebView an SDK?

It is a platform component and API, rather than a single cross-platform SDK. Android and Apple provide separate implementations with different configuration and lifecycle details.

Can I embed any website?

You can try to load a URL in a native web view, but the site may depend on browser features, block the context, or behave differently. A website iframe is additionally subject to framing policies.

Should authentication happen in a WebView?

Choose an authentication flow designed for the identity provider and platform. Do not assume that placing a login page in an embedded view is accepted or secure for every provider.

Can a web view work without internet?

Yes, if the required content and dependencies are bundled or otherwise available locally. Remote content and APIs still require connectivity.

Does ScreenshotNeo replace a WebView?

No. ScreenshotNeo captures a rendered page as an image or PDF. It is useful for visual review and automation, not for showing an interactive web page inside an app.