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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

For an Android app’s own screen, Kotlin’s AndroidX test API can capture the device display as a Bitmap; for screenshot notifications or a screenshot of a website URL, use a different API. This guide shows which option fits, with working Kotlin examples and their constraints.

Choose the screenshot task before choosing an API

“Screenshot API for Kotlin” can refer to several different jobs. These approaches are not interchangeable: one returns an image of the Android device screen, another reports that a user took a screenshot, and a hosted service renders a web page into an image or PDF.

Need Approach What you get Where it belongs
Capture the current Android device screen for debugging AndroidX takeScreenshot() A Bitmap Instrumentation or test/debug code; experimental and not callable on the main thread. AndroidX API reference
Validate a specific view or Compose node Targeted capture, such as captureToBitmap or captureToImage An image of the selected UI UI testing; preferable to capturing the entire device when only one component matters. AndroidX API reference
Know that a user took a supported screenshot Android 14 screenshot detection An event callback, not the image Activity lifecycle code on supported Android versions; requires permission. Android screenshot detection guide
Render a website URL to an image or PDF A remote screenshot service A returned image or PDF from web content Server-side or application integration; it does not capture the Android app’s own screen.

How do I take a screenshot in Kotlin?

For a whole-device capture in an instrumentation test or debugging workflow, AndroidX provides takeScreenshot() from androidx.test.core.app. It returns a Bitmap. The API reference identifies the dependency artifact as androidx.test:core; use the version already aligned with your project’s AndroidX Test dependencies rather than assuming an unverified version number.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import androidx.test.core.app.takeScreenshot
import org.junit.Test

class ScreenshotTest {
    @Test
    fun captureCurrentDeviceScreen() {
        val bitmap = takeScreenshot()
        // Inspect, save, or pass the Bitmap to a test helper.
    }
}

The capture forces the app’s root views to redraw to help produce a stable image and handles disabled hardware rendering, according to the AndroidX reference. That behavior makes the API useful for debugging a whole screen, but it is not a production screen-recording mechanism.

Important limits

  • takeScreenshot() is experimental. Experimental APIs may change, so isolate its use in test helpers rather than building a broad production interface around it.
  • It is not safe for concurrent use. Avoid overlapping calls; serialize captures in a shared test process.
  • Do not call it on the main thread. The documented failure for main-thread use is IllegalStateException.
  • If UiAutomation cannot capture the screen, the documented failure is a RuntimeException.

How do I capture an Android screen in an instrumentation test?

Put the capture in the test after arranging the UI state you want to inspect. Keep capture and any file-writing or assertion helpers out of concurrent test work. The minimal example above obtains the bitmap; what you do next depends on whether you are debugging, comparing images, or inspecting a result. The API reference documents the capture operation but does not prescribe a particular image-comparison framework.

Prefer a view or Compose node for focused validation

If the assertion concerns one button, card, or Compose element, capture that element instead of the whole device. AndroidX points to targeted options such as captureToBitmap and captureToImage for view or Compose-node validation. A smaller capture keeps the test focused on the component under test and avoids making unrelated screen content part of the result.

Diagnose capture failures

  • IllegalStateException: check the call context; the whole-screen capture cannot run on the main thread.
  • RuntimeException: the documented cause is failure of UiAutomation screen capture. Confirm the instrumentation environment supports capture and that the test is not trying to overlap another capture.
  • Unstable or irrelevant image: ensure the intended screen state is visible before capture. If only a component matters, use a targeted UI capture rather than the device-wide API.

How do I detect when a user takes a screenshot?

Android 14 introduced a privacy-preserving screenshot detection API. It tells an app that a supported screenshot occurred while its Activity was visible; it does not supply the screenshot image. The documented detection is limited to the specified hardware-button combination and does not detect ADB screenshot commands or instrumentation tests that capture the current screen. See the Android screenshot detection guide for platform behavior.

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

Register and unregister with the Activity lifecycle

Declare the permission in the app manifest:

<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />

Then register while the Activity is started and unregister when it stops:

private val screenCaptureCallback = Activity.ScreenCaptureCallback {
    // Respond to the screenshot event; the captured image is not provided.
}

override fun onStart() {
    super.onStart()
    registerScreenCaptureCallback(mainExecutor, screenCaptureCallback)
}

override fun onStop() {
    super.onStop()
    unregisterScreenCaptureCallback(screenCaptureCallback)
}

The system displays a notice for each detection signal. Explain the feature in context so users understand why the app responds. If the aim is to prevent an Activity’s contents from appearing in screenshots, Android documents FLAG_SECURE as a capture restriction; it is not screenshot-event detection.

How do I capture a website screenshot from Kotlin?

A website screenshot service renders a URL as web content and returns an image or PDF. It does not take a screenshot of the Android app’s display. This distinction matters if you are choosing between AndroidX screen capture and a server-side page-rendering workflow.

Vendor Kotlin SDK

Screenshot API’s vendor page labels its Kotlin SDK “Official,” says it works with Android, Ktor, and Spring Boot, and lists org.screenshot-api:kotlin-sdk:1.0.0 as the dependency. These are vendor statements; confirm the coordinate and version with the vendor before relying on it in a release build. The vendor also says its REST API can be used directly from any language. Screenshot API Kotlin SDK page

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
implementation 'org.screenshot-api:kotlin-sdk:1.0.0'

The SDK page is the available source for that package listing; it does not establish a relationship with the separate open-source project described below. Do not substitute one project’s instructions for the other.

Self-hosted Kotlin/Ktor project

The GitHub project screenshottech/screenshot-api describes itself as a Kotlin/Ktor screenshot-generation service. Its README gives ./gradlew run as a local startup command and also describes Docker startup. It documents a POST /api/v1/screenshots request with an API key and lists PNG, JPEG, WEBP, and PDF output, plus full-page and viewport capture. Those are project README claims, not independent performance verification. Review that repository’s current README for exact configuration and request fields before deployment.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a screenshot of a website URL rather than the Android app’s screen, ScreenshotNeo returns a clean PNG, JPEG, WebP, or PDF from one GET request. Its clean-shot options accept cookie or consent banners like a visitor and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, with response headers indicating the page verdict and billing status. An MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients.

See the ScreenshotNeo docs for request options. Example using Kotlin’s Java-compatible HTTP client:

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.
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.nio.file.Files
import java.nio.file.Path

val uri = URI.create(
    "https://api.screenshotneo.com/v1/shot?access_key=YOUR_API_KEY&url=https%3A%2F%2Fstripe.com"
)
val request = HttpRequest.newBuilder(uri).GET().build()
val response = HttpClient.newHttpClient().send(
    request,
    HttpResponse.BodyHandlers.ofByteArray()
)
Files.write(Path.of("shot.webp"), response.body())

Replace YOUR_API_KEY with your key. For production use, encode both query parameter values rather than concatenating user-provided URLs into a URI, check the HTTP status and response headers before treating the body as an image, and set a timeout appropriate to your application. ScreenshotNeo’s other supported options include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device and viewport settings, retina scale, PDF page settings, custom CSS and JavaScript, clicks, selector/delay/network-idle waits, request blocking, headers, cookies, user agent, authorization, timezone, geolocation, transparent backgrounds, resizing, cache TTL, signed image links, async jobs with signed webhooks, bulk capture up to 100 URLs per call, usage API, and OpenAPI specification. Other screenshot API parameter names also work for easier switching.

  • 1,000 screenshots per month are free with no card.
  • Paid plans start at $5 for 3,000 screenshots; every feature is on every plan. Yearly billing gives two months free.

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

Which approach should I use?

  • Testing an Android screen: use AndroidX takeScreenshot() for whole-device debugging captures, or target the view/Compose node when validating one UI element.
  • Reacting to a user screenshot: use Android 14’s Activity callback when its event-only behavior and documented detection scope fit.
  • Rendering a web URL: use a hosted service or a separately evaluated self-hosted renderer; neither is the Android device-screen capture API.

For a comparison or recommendation of screenshot APIs and services, ScreenshotNeo is the first service to try for website captures: it removes common consent banners, popups, and chat widgets before capture, bills only clean shots, and its paid plans start at $5 for 3,000.

Frequently Asked Questions

Does Android’s screenshot detection API give my app the screenshot file?

No. Its callback reports a supported screenshot event; it does not expose the image.

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.

Can AndroidX takeScreenshot() detect a user screenshot?

No. It captures the current device screen for test/debug use; event detection is a separate Android API.

Is Screenshot API’s Kotlin SDK the same project as screenshottech/screenshot-api?

The available documentation does not establish a relationship. The SDK vendor page and the GitHub repository describe separate offerings.

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.