diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
index d178517614a9d1..bfca36f45fae26 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
@@ -48,6 +48,18 @@ public class ObjcCommandLineOptions extends FragmentOptions {
               + "devicetypes' on the machine the simulator will be run on.")
   public String iosSimulatorDevice;
 
+  @Option(
+    name = "ios_device",
+    defaultValue = "null",
+    documentationCategory = OptionDocumentationCategory.TESTING,
+    effectTags = {OptionEffectTag.TEST_RUNNER},
+    help =
+        "The identifier, ECID, serial number, UDID, user-provided name, or DNS name of "
+            + "the device for running an iOS application. "
+            + "You can get a list of devices by running 'xcrun devicectl list "
+            + "devices'.")
+  public String iosDevice;
+
   @Option(
     name = "ios_memleaks",
     defaultValue = "false",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
index 8e803eba7e8d64..5f3e2677443f8c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
@@ -53,6 +53,7 @@ public class ObjcConfiguration extends Fragment implements ObjcConfigurationApi
 
   private final DottedVersion iosSimulatorVersion;
   private final String iosSimulatorDevice;
+  private final String iosDevice;
   private final boolean runMemleaks;
   private final CompilationMode compilationMode;
   private final ImmutableList<String> fastbuildOptions;
@@ -70,6 +71,7 @@ public ObjcConfiguration(BuildOptions buildOptions) {
 
     this.iosSimulatorDevice = objcOptions.iosSimulatorDevice;
     this.iosSimulatorVersion = DottedVersion.maybeUnwrap(objcOptions.iosSimulatorVersion);
+    this.iosDevice = objcOptions.iosDevice;
     this.runMemleaks = objcOptions.runMemleaks;
     this.compilationMode = Preconditions.checkNotNull(options.compilationMode, "compilationMode");
     this.fastbuildOptions = ImmutableList.copyOf(objcOptions.fastbuildOptions);
@@ -98,6 +100,14 @@ public DottedVersion getIosSimulatorVersion() {
     return iosSimulatorVersion;
   }
 
+  /**
+   * Returns the device when running an application on a physical device.
+   */
+  @Override
+  public String getIosDevice() {
+    return iosDevice;
+  }
+
   @Override
   public boolean runMemleaks() {
     return runMemleaks;
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ObjcConfigurationApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ObjcConfigurationApi.java
index bcbcb596d910e1..537ef45e7f0c67 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ObjcConfigurationApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ObjcConfigurationApi.java
@@ -48,6 +48,14 @@ public interface ObjcConfigurationApi extends StarlarkValue {
   @Nullable
   DottedVersionApi<?> getIosSimulatorVersion();
 
+  @StarlarkMethod(
+      name = "ios_device",
+      structField = true,
+      allowReturnNones = true,
+      doc = "The device identifier to use when running an iOS application.")
+  @Nullable
+  String getIosDevice();
+
   @StarlarkMethod(
       name = "run_memleaks",
       structField = true,
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcStarlarkTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcStarlarkTest.java
index baec12578d2d95..9c2a15f74e4c2a 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcStarlarkTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcStarlarkTest.java
@@ -808,6 +808,61 @@ def swift_binary_impl(ctx):
     assertThat(signingCertificateName).isEqualTo("'Apple Developer'");
   }
 
+  @Test
+  public void testStarlarkCanAccessObjcConfigurationForDevice() throws Exception {
+    scratch.file("examples/rule/BUILD");
+    scratch.file(
+        "examples/rule/objc_rules.bzl",
+        """
+        load("//myinfo:myinfo.bzl", "MyInfo")
+
+        def swift_binary_impl(ctx):
+            compilation_mode_copts = ctx.fragments.objc.copts_for_current_compilation_mode
+            ios_device = ctx.fragments.objc.ios_device
+            signing_certificate_name = ctx.fragments.objc.signing_certificate_name
+            return MyInfo(
+                compilation_mode_copts = compilation_mode_copts,
+                ios_device = ios_device,
+                signing_certificate_name = signing_certificate_name,
+            )
+
+        swift_binary = rule(
+            implementation = swift_binary_impl,
+            fragments = ["objc"],
+        )
+        """);
+
+    scratch.file("examples/objc_starlark/a.m");
+    scratch.file(
+        "examples/objc_starlark/BUILD",
+        """
+        load("//examples/rule:objc_rules.bzl", "swift_binary")
+
+        package(default_visibility = ["//visibility:public"])
+
+        swift_binary(
+            name = "my_target",
+        )
+        """);
+
+    useConfiguration(
+        "--compilation_mode=opt",
+        "--ios_multi_cpus=arm64",
+        "--ios_device='11111111-1111-1111-1111-11111111111'",
+        "--ios_signing_cert_name='Apple Developer'");
+    ConfiguredTarget starlarkTarget = getConfiguredTarget("//examples/objc_starlark:my_target");
+    StructImpl myInfo = getMyInfoFromTarget(starlarkTarget);
+
+    @SuppressWarnings("unchecked")
+    List<String> compilationModeCopts = (List<String>) myInfo.getValue("compilation_mode_copts");
+    Object iosDevice = myInfo.getValue("ios_device");
+    Object signingCertificateName = myInfo.getValue("signing_certificate_name");
+
+    assertThat(compilationModeCopts).containsExactlyElementsIn(ObjcConfiguration.OPT_COPTS);
+    assertThat(iosDevice).isEqualTo("'11111111-1111-1111-1111-11111111111'");
+    assertThat(signingCertificateName).isEqualTo("'Apple Developer'");
+  }
+
   @Test
   public void testSigningCertificateNameCanReturnNone() throws Exception {
     scratch.file("examples/rule/BUILD");