diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java
index c58a71c8b7ef..1be1f16115ad 100644
--- a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java
+++ b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java
@@ -40,10 +40,14 @@
 import java.lang.reflect.Method;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.Enumeration;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.ServiceLoader;
 import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -56,6 +60,11 @@ public abstract class ServiceOptions<
   private static final String DEFAULT_HOST = "https://www.googleapis.com";
   private static final long serialVersionUID = 1203687993961393350L;
   private static final String PROJECT_ENV_NAME = "GCLOUD_PROJECT";
+  private static final String MANIFEST_ARTIFACT_ID_KEY = "artifactId";
+  private static final String MANIFEST_VERSION_KEY = "Implementation-Version";
+  private static final String ARTIFACT_ID = "gcloud-java-core";
+  private static final String APPLICATION_BASE_NAME = "gcloud-java";
+  private static final String APPLICATION_NAME = getApplicationName();
 
   private final String projectId;
   private final String host;
@@ -522,6 +531,13 @@ public Clock clock() {
     return clock;
   }
 
+  /**
+   * Returns the application's name as a string in the format {@code gcloud-java/[version]}.
+   */
+  public String applicationName() {
+    return APPLICATION_NAME;
+  }
+
   protected int baseHashCode() {
     return Objects.hash(projectId, host, httpTransportFactoryClassName, authCredentialsState,
         retryParams, serviceFactoryClassName, serviceRpcFactoryClassName, connectTimeout,
@@ -568,4 +584,23 @@ private static <T> T newInstance(String className) throws IOException, ClassNotF
   private static <T> T getFromServiceLoader(Class<? extends T> clazz, T defaultInstance) {
     return Iterables.getFirst(ServiceLoader.load(clazz), defaultInstance);
   }
+
+  private static String getApplicationName() {
+    String version = null;
+    try {
+      Enumeration<URL> resources =
+          ServiceOptions.class.getClassLoader().getResources(JarFile.MANIFEST_NAME);
+      while (resources.hasMoreElements() && version == null) {
+        Manifest manifest = new Manifest(resources.nextElement().openStream());
+        Attributes manifestAttributes = manifest.getMainAttributes();
+        String artifactId = manifestAttributes.getValue(MANIFEST_ARTIFACT_ID_KEY);
+        if (artifactId != null && artifactId.equals(ARTIFACT_ID)) {
+          version = manifestAttributes.getValue(MANIFEST_VERSION_KEY);
+        }
+      }
+    } catch (IOException e) {
+      // ignore
+    }
+    return version != null ? APPLICATION_BASE_NAME + "/" + version : APPLICATION_BASE_NAME;
+  }
 }
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
index 90f2c98ad4b8..349cfbf771cb 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
@@ -85,7 +85,7 @@ public DefaultStorageRpc(StorageOptions options) {
     this.options = options;
     storage = new Storage.Builder(transport, new JacksonFactory(), initializer)
         .setRootUrl(options.host())
-        .setApplicationName("gcloud-java")
+        .setApplicationName(options.applicationName())
         .build();
   }