If you already have an iOS app that lets users pick, capture, or upload images, the fastest way to add background removal is to send the image to the BackgroundErase API and display the returned transparent PNG in your interface. This approach keeps the integration lightweight and avoids shipping a large on-device ML model.
Best fit: This workflow is ideal for teams that want to add background removal to an existing iPhone or iPad app quickly, without building and maintaining an on-device segmentation pipeline.
Want to test this first? Start with a free trial on BackgroundErase pricing to get API access and run the integration end to end before deciding on a larger deployment.
Why add background removal through the API?
Using the API is usually the quickest path because your app only needs to upload an image and render the result. That makes it easy to launch the feature fast and improve it later without changing your mobile model package or app bundle.
- Fastest path to shipping a background removal feature
- No on-device model packaging or Core ML conversion required
- Easy to add into an existing SwiftUI or UIKit flow
- Results improve on the server side without app updates
- Simple to save, share, or upload the finished PNG
The 10-minute integration flow
At a high level, the integration looks like this:
- Start a free trial and get your API key
- Add your BackgroundErase API key to Info.plist
- Create a tiny Swift API client with URLSession
- Let the user choose or capture a photo
- Send the image to BackgroundErase
- Render the returned transparent PNG in your SwiftUI view
- Save or share the final result
Test the API with one image first
Before wiring the feature into your app, it helps to verify the endpoint with a single test image:
curl -H 'x-api-key: YOUR_API_KEY' \
-f https://api.backgrounderase.com/v2 \
-F 'image_file=@/absolute/path/to/photo.jpg' \
-F 'format=png' \
-F 'size=full' \
-o output.pngOnce this returns a valid transparent PNG, you know your API key and request format are correct before moving into Xcode.
Add your API key to Info.plist
Store your key in your app configuration so your networking layer can read it at runtime:
<!-- Info.plist -->
<key>BG_ERASE_API_KEY</key>
<string>YOUR_API_KEY</string>Note: For production apps, many teams proxy requests through their own backend so the mobile app does not directly expose long-lived secrets.
Create a small Swift API client
This client takes a UIImage, uploads it as multipart form data, and returns the processed cutout as another UIImage.
import Foundation
import UIKit
final class BackgroundEraseClient {
private let endpoint = URL(string: "https://api.backgrounderase.com/v2")!
private let apiKey: String = {
guard let key = Bundle.main.object(
forInfoDictionaryKey: "BG_ERASE_API_KEY"
) as? String, !key.isEmpty else {
fatalError("Missing BG_ERASE_API_KEY in Info.plist")
}
return key
}()
func removeBackground(from image: UIImage) async throws -> UIImage {
guard let imageData = image.jpegData(compressionQuality: 0.95) else {
throw URLError(.cannotEncodeContentData)
}
let boundary = "Boundary-\(UUID().uuidString)"
var request = URLRequest(url: endpoint)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
request.setValue(
"multipart/form-data; boundary=\(boundary)",
forHTTPHeaderField: "Content-Type"
)
request.httpBody = makeBody(
boundary: boundary,
fileData: imageData,
fileName: "photo.jpg",
mimeType: "image/jpeg"
)
let (data, response) = try await URLSession.shared.data(for: request)
guard let http = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
guard (200...299).contains(http.statusCode) else {
let body = String(data: data, encoding: .utf8) ?? "Unknown API error"
throw NSError(
domain: "BackgroundEraseAPI",
code: http.statusCode,
userInfo: [NSLocalizedDescriptionKey: body]
)
}
guard let output = UIImage(data: data) else {
throw URLError(.cannotDecodeContentData)
}
return output
}
private func makeBody(
boundary: String,
fileData: Data,
fileName: String,
mimeType: String
) -> Data {
var body = Data()
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"image_file\"; filename=\"\(fileName)\"\r\n")
body.append("Content-Type: \(mimeType)\r\n\r\n")
body.append(fileData)
body.append("\r\n--\(boundary)--\r\n")
return body
}
}
private extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}Connect it to your SwiftUI screen
The example below uses PhotosPicker to let the user choose an image, then sends it to BackgroundErase and renders the result in the same view:
import SwiftUI
import PhotosUI
@MainActor
final class RemoveBackgroundViewModel: ObservableObject {
@Published var inputImage: UIImage?
@Published var outputImage: UIImage?
@Published var isLoading = false
@Published var errorMessage: String?
private let client = BackgroundEraseClient()
func processSelectedItem(_ item: PhotosPickerItem?) async {
guard let item else { return }
do {
guard let data = try await item.loadTransferable(type: Data.self),
let image = UIImage(data: data) else {
errorMessage = "Could not load the selected image."
return
}
inputImage = image
outputImage = nil
errorMessage = nil
isLoading = true
let result = try await client.removeBackground(from: image)
outputImage = result
isLoading = false
} catch {
isLoading = false
errorMessage = error.localizedDescription
}
}
}
struct ContentView: View {
@StateObject private var viewModel = RemoveBackgroundViewModel()
@State private var selectedItem: PhotosPickerItem?
var body: some View {
NavigationStack {
VStack(spacing: 20) {
PhotosPicker(selection: $selectedItem, matching: .images) {
Text("Choose Photo")
.frame(maxWidth: .infinity)
.padding()
.background(Color.black.opacity(0.06))
.clipShape(RoundedRectangle(cornerRadius: 14))
}
.onChange(of: selectedItem) { _, newValue in
Task {
await viewModel.processSelectedItem(newValue)
}
}
if viewModel.isLoading {
ProgressView("Removing background...")
}
if let image = viewModel.outputImage {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(maxHeight: 360)
} else if let image = viewModel.inputImage {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(maxHeight: 360)
}
if let error = viewModel.errorMessage {
Text(error)
.font(.footnote)
.foregroundStyle(.red)
}
Spacer()
}
.padding()
.navigationTitle("Background Removal")
}
}
}From there, you can add save, share, or upload actions depending on the rest of your app flow.
UX tips for a polished iOS integration
A small amount of product polish makes the feature feel much more native inside your app.
- Show a loading state while the image is processing
- Keep the original image visible until the result returns
- Surface API failures with a short, clear error message
- Let users compare before and after results
- Offer save and share actions once processing finishes
- Resize overly large source images before upload when appropriate
Tip: The simplest first version is often just: choose photo, process, preview, save. You can add batch flows, history, or editing tools later.
API-based vs on-device background removal
For most teams, the API is the fastest way to ship because it removes the need to package models, manage memory constraints, and tune inference behavior across devices. We also offer BackgroundErase on-device for teams that want lower latency and no per-call API costs once the model is embedded directly into their application stack.
- Choose the API for fastest time to launch
- Choose the API when you want the lightest app bundle
- Choose on-device when low latency is a priority
- Choose on-device when you want to eliminate per-call API costs
Ready to try it?
If you want to get this working quickly, start with a free trial on backgrounderase.com/pricing and test the API inside your iOS app.
If you need an on-device deployment for lower latency and zero per-call API charges, or want to discuss licensing for a larger mobile product, go to backgrounderase.com/enterprise and fill out the form.
