Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)

Storing and Retrieving Metadata

Every instance has metadata associated with it. Some of this metadata can be defined by the user, and other information, such as the host name, is assigned by Google Compute Engine during the startup process.

Compute Engine might offer more than one metadata version at a single time, but it is recommended that you always use the newest metadata server version available. At any time, Google Compute Engine can add new entries to the metadata server and add new fields to responses. Check back periodically for changes!

Current version: v1


Metadata server

Every instance stores its metadata on the metadata server. You can query this metadata server programmatically for information such as the instance's host name, instance ID, startup scripts, and custom metadata. It also provides access to service account information. Your instance automatically has access to the metadata server API without any additional authorization.

Metadata is stored in the format key:value . There is a default set of metadata entries that every instance has access to and you can also choose to create custom metadata . To query for certain metadata, you can construct a request to the metadata server using the URL or the IP address.

  • Full URL:
  • Shorthand URL: http://metadata/computeMetadata/v1/
  • IP address:

For more information, see querying metadata .

Default metadata

Google Compute Engine defines a set of default metadata entries that provide information about your instance or project. Default metadata is always defined and set by the server. You cannot manually edit any of these metadata pairs.

The following is a list of default metadata available to a project. Some metadata entries are directories that contain other metadata keys. This difference is marked by a trailing slash in the metadata name. For example, attributes/ is a directory that contains other keys, while numeric-project-id is a metadata key or endpoint that maps to a value.

Relative to
Metadata Entry Description
attributes/ A directory of custom metadata values that are passed to the project.
attributes/sshKeys A list of ssh keys that can be used to connect to instances in the project.
numeric-project-id The numeric project ID of the instance, which is not the same as the project name visible in the Google Developers Console . Do not use this as the project with gcloud compute ; instead, use the project-id metadata entry value.
project-id The project ID .

The following is a list of default metadata available to an instance:

Relative to
Metadata Entry Description
attributes/ A directory of custom metadata values passed to the instance during startup. See Specifying Custom Metadata below.
description The free-text description of an instance, assigned using the --description flag, or set in the API.
disks/ A directory of disks attached to this instance.
hostname The host name of the instance.
id The ID of the instance. This is a unique, numerical ID that is generated by Google Compute Engine. This is useful for identifying instances if you do not want to use instance names.
image The fully-qualified image name.
machine-type The fully-qualified machine type name of the instance's host machine.
network-interfaces/ A directory of network interfaces for the instance.
network-interfaces/ <index> /forwarded-ips/ A directory of any external IPs that are currently pointing to this virtual machine instance, for the network interface at <index> . Specifically, provides a list of external IPs served by forwarding rules that direct packets to this instance.
scheduling/ A directory with the scheduling options for the instance.
scheduling/on-host-maintenance The instance's scheduled maintenance event behavior setting. This value is set with the ‑‑on_host_maintenance flag or via the API.
scheduling/automatic-restart The instance's automatic restart setting. This value is set with the ‑‑automatic_restart flag or via the API.
maintenance-event The path that indicates that a scheduled maintenance event is affecting this instance. See Scheduled maintenance notice for details.
project-id The instance's project ID. You can use this the project for gcloud compute commands.
service-accounts/ A directory of service accounts associated with the instance.
tags Any tags associated with the instance.
zone The instance's zone.

Querying metadata

You can query a metadata server only from its associated instance. You cannot query an instance's metadata from another instance or directly from your local computer. For example, you would send a curl or wget command from the instance to its metadata server.

You can query the metadata server using the root metadata server URL or the IP address. All of these URLs will work for your metadata requests.

  • Full URL:
  • Shorthand URL: http://metadata/computeMetadata/v1/
  • IP address:

These are the root URLs for all instance and project metadata. Specific metadata values are defined as sub-paths below these root URLs.

When you query the metadata server, you must also provide the following header in all of your requests:

Metadata-Flavor: Google

This header indicates that the request was sent with the intention of retrieving metadata values, rather than unintentionally from an insecure source, and allows the metadata server to return the data you requested. If you do not provide this header, the metadata server denies your request.

Depending on the type of query you make, the metadata server can return data in a number of ways.

Querying directory listings

The metadata server uses directories to organize certain metadata keys. Any metadata entry ending in a trailing slash is a directory. For example, the disks/ entry is a directory of disks attached to that instance:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

Similarly, if you wanted more information about the 1/ directory, you can query the specific URL for that directory:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

Querying metadata endpoints

Other metadata entries are keys or endpoints that return one or more values. To query for data from a metadata endpoint, send a query to that particular endpoint. For example, to query the mode of a specific disk, query the following endpoint:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

By default, each endpoint defines the format for returned data. Some endpoints might return data in JSON format by default, while other endpoints might return data as a string. You can override the default data format specification by using the alt=json or alt=text query parameters, which returns data in JSON string format or as a plaintext representation, respectfully.

For example, the tags key automatically returns data in JSON format. You can choose to return data in text format instead, by specifying the alt=text query parameter:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

Querying recursive contents

If you want to return all contents underneath a directory, use the recursive=true query parameter with your request:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

By default, recursive contents are returned in JSON format. If you want to return these contents in text format, append the alt=text query parameter:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"
0/device-name boot
0/index 0
1/device-name persistent-disk-1
1/index 1
2/device-name persistent-disk-1
2/index 2
2/mode READ_ONLY

Detecting if you are running in Compute Engine

You can easily detect if your applications or scripts are running within a Compute Engine instance by using the metadata server. When you make a request to the server, any response from the metadata server will contain the Metadata-Flavor: Google header. You can look for this header to reliably detect if you are running in Compute Engine.

For example, the following curl request returns a Metadata-Flavor: Google header, indicating that the request is being made from within a Compute Engine instance.

me@my-inst:~$ curl -i
HTTP/1.1 200 OK
Metadata-Flavor: Google
Content-Type: application/text
Date: Thu, 10 Apr 2014 19:24:27 GMT
Server: Metadata Server for VM
Content-Length: 22
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN


Specifying custom metadata

You can set custom metadata for an instance or project outside of the server- defined metadata. This is useful for passing in arbitrary values to your project or instance that can be queried by your code on the instance.

When you specify custom metadata, the metadata server stores it in the attributes/ directory for that instance or project. To query for all the custom metadata available to an instance or project, query the attributes/ directory:

curl "<instance|project>/attributes/" -H "Metadata-Flavor: Google"

Setting custom instance metadata

You can set custom metadata for an instance either using the --metadata flag during instance creation, or by using the gcloud compute add-metadata method on a running instance. Setting metadata is additive, so you only need to specify the metadata keys that you want to add or change. If you specify an existing key, then the key's value will be updated.

Setting metadata during instance creation

To pass in custom metadata during instance creation, provide the --metadata flag with your request. You can provide this flag as many times as you would like, and pass in multiple metadata pairs. The following example demonstrates starting a new instance with the key "bread" and the value "butter", and querying it from the instance.

$ gcloud compute instances create myinstance --metadata bread=butter
... select a zone...
Created [].
myinstance us-central1-a n1-standard-1 RUNNING    ...

$ gcloud compute ssh myinstance
user@myinstance:~$ curl "" -H "Metadata-Flavor: Google"

Updating or setting metadata on a running instance

If you want to set or update the metadata entries for a running instance, you can use the instances add-metadata command:

$ gcloud compute instances add-metadata INSTANCE --metadata key-1=value-1 key-2=value-2  key-n=value-n

Because metadata updates are additive, you need to specify only the metadata keys that you want to add or change. If you specify an existing key, then the key's value will be updated with the new value. For example, assume your instance metadata looks like this:

  fingerprint: _OW8mWFLqsk=
  - key: bread
    value: mayo
  - key: cheese
    value: cheddar
  - key: lettuce
    value: butter

If you want to change the lettuce=butter entry to lettuce=green , use:

$ gcloud compute instances add-metadata INSTANCE --metadata lettuce=green

If you want to remove the lettuce=butter entry, use:

$ gcloud compute instances remove-metadata INSTANCE --keys lettuce

Applying a startup script using custom metadata

The custom metadata option is especially useful for specifying startup scripts that run during instance boot. Startup scripts can be used to install software, check and start services, or set custom environment variables. With gcloud compute , you can pass in startup scripts using the --metadata flag or from a local file using the --metadata-from-file flag. The --metadata-from-file flag is useful for passing in in script content that is too large to pass in with the --metadata flag.

In images that have the Cloud SDK installed on them, the metadata keys startup-script and startup-script-url are reserved for passing in script- related metadata.

For example:

  • Passing in a startup script from a local file:
    gcloud compute instances create example-instance --metadata-from-file startup-script=FILE
  • Passing in a startup script from Google Cloud Storage:
    gcloud compute instances create example-instance --metadata startup-script-url=URL
  • Passing in your startup script directly:
    gcloud compute instances create example-instance --metadata startup-script="#! /bin/bash
    > # Installs apache and a custom homepage
    > apt-get update
    > apt-get install -y apache2
    > cat <<EOF > /var/www/index.html
    > <html><body><h1>Hello World</h1>
    > <p>This page was created from a simple start up script!</p>
    > </body></html>
    > EOF"

For more information about startup scripts and how to use them, see Using Startup Scripts .

Setting project-wide custom metadata

If you want to set project-level custom metadata, which is accessible by all instances in that project, you can do so using the add-metadata command. For example, if you define a project-wide metadata pair of baz=bat , the metadata pair is automatically available to all instances at the project/attributes/ directory:

To set project-wide metadata using gcloud compute , use the project-info add-metadata command. For example:

$ gcloud compute project-info add-metadata --metadata foo=bar baz=bat
$ gcloud compute project-info describe
  fingerprint: RfOFY_-eS64=
  - key: baz
    value: bat
  - key: foo
    value: bar
  - key: sshKeys

One metadata key-value pair is specified with an equals sign, for example, key=value . Multiple key-value pairs are separated with spaces.

You can optionally specify one or more files from which to read metadata using the --metadata-from-file flag.

Updating project-wide metadata

Similar to instance metadata, project metadata updates are additive. This means that you need to only specify the metadata keys that you want to add or change. If you specify an existing key, then the key's value will be updated with the new value. For example, assume you have the following metadata entries:

  fingerprint: PceRYYVzGbo8=
  - key: baz
    value: bat
  - key: foo
    value: bar
  - key: try
    value: eat
  - key: car
    value: saw

If you wanted to update the metadata value for baz and foo , then you need to only specify those keys in the gcloud compute command.

$ gcloud compute project-info add-metadata --metadata baz=new foo=new

If you're updating metadata that might be several strings long, you might want to use the --metadata-from-file flag, which reads in the contents of a file as the key value:

$ gcloud compute project-info add-metadata --metadata-from-file KEY=FILE

This is especially useful for setting metadata attributes like sshKeys, which is usually a random combination of several strings. Rather than providing the raw string value, you could just save the string in the file and provide the file with the --metadata-from-file flag.

Waiting for change

Given that metadata values can change while your instance is running, the metadata server offers the ability to be notified of metadata changes using the wait-for-change feature. This feature allows you to perform hanging HTTP GET requests that only return when your specified metadata has changed. You can use this feature on custom metadata or server-defined metadata, so if anything changes about your instance or project, or if someone updates a custom metadata, you can programmatically react to the change. For example, you can perform a request on the tags key so that the request only returns if the contents of the tags metadata has changed. When the request returns, it provides the new value of that metadata key.

To perform a wait-for-change request, query a metadata key and append the ?wait_for_change=true query parameter:

user$myinst:~$ curl "" -H "Metadata-Flavor: Google"

After there is a change to the specified metadata key, the query returns with the new value. In this example, if a request is made to the setInstanceTags method, the request returns with the new values:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

You can also perform a wait-for-change request recursively on the contents of a directory:

user$myinst:~$ curl "" -H "Metadata-Flavor: Google"

The metadata server returns the new contents if there is any change:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

The wait-for-change feature also lets you match with your request and set timeouts .

Using ETags

If you submit a simple wait-for-change query, the metadata server returns if anything has changed in the contents of that metadata. However, there is an inherent race condition between a metadata update and a wait-for-change request being issued, so it is useful to have a reliable way to know you are getting the latest metadata value. To help with this, you can use the last_etag query parameter, which compares the ETag value you provide with the ETag value saved on the metadata server. If the ETag values match, then the wait-for-change request will be accepted. If the ETag values do not match, this indicates that the contents of the metadata has changed since the last time you retrieved the ETag value, and the metadata server returns immediately with this latest value.

To grab the current ETag value for a metadata key, make a request to that key and print the headers. In CURL, you can do this with the -v flag:

user@myinst:~$ curl -v "" -H "Metadata-Flavor: Google"
* About to connect() to metadata port 80 (#0)
*   Trying connected
* Connected to metadata ( port 80 (#0)
> GET /computeMetadata/v1/instance/tags?wait_for_change=true HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/ libidn/1.15
> Host: metadata
> Accept: */*
< HTTP/1.1 200 OK
< Content-Type: application/text
< ETag: 411261ca6c9e654e
< Date: Wed, 13 Feb 2013 22:43:45 GMT
< Server: Metadata Server for VM
< Content-Length: 26
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN

You can also grab the ETag programmatically. The following example uses Python to extract the ETag value from the metadata response:

import httplib2

def main():
  http = httplib2.Http()
  response, content = http.request('',
                                   headers={'Metadata-Flavor': 'True'})
  etag = response['etag']

  print etag

if __name__ == '__main__':

Use that ETag value in your wait-for-change request:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

The metadata server will match your specified ETag value and if that value changes, the request returns with the new contents of your metadata key.

Using 0 As Your ETag Value

The metadata server will never return 0 as an ETag. You could use that information to simplify some of your code. For example, the following code example sets the initial ETag value as 0, performs a request to the server, which immediately returns with the initial data and the current ETag value, and then uses that information to wait for a change. This method would save you from writing additional lines of code to grab the first initial ETag.

import httplib2


def main():
  http = httplib2.Http()
  tagsUrl = METADATA_URL + 'instance/tags?wait_for_change=true'

  # set the first last_etag as 0
  last_etag = 0
  while True:
    # returns immediately on the initial request because 0 is invalid
    # otherwise wait until something changes
    resp,content = http.request(uri=tagsUrl + '&last_etag=' + str(last_etag), method='GET', body='', headers={'Metadata-Flavor': 'True'})

    if resp != 500:
      last_etag = resp['etag']
      print content

if __name__ == '__main__':

Setting timeouts

If you would like your wait-for-change request to time out after a certain number of seconds, you can set the timeout_sec=<timeout-in-seconds> query parameter. The timeout_sec parameter limits the wait time of your request to the number of seconds you specified and when the request reaches that limit, it returns the current contents of the metadata key. Here is an example of a wait-for-change request that is set to time out after 360 seconds:

user@myinst:~$ curl "" -H "Metadata-Flavor: Google"

When you set the timeout_sec parameter, the request always returns after the specified number of seconds, whether or not the metadata value has actually changed. It is only possible to set an integer value for your timeout.

Status codes

When you perform a wait-for-change request, the metadata server returns standard HTTP status codes to indicate success or failure. In the case of errors, network conditions can cause the metadata server to fail your request and return an error code. In these cases, you should design your application to be fault-tolerant and to be able to recognize and handle these errors.

The possible statuses that the metadata server returns are:

Status Description
HTTP 200 Success! A value was changed, or you reached your specified timeout_sec and the request returned successfully.
Error 400 Your request was invalid. Please fix your query and retry the request.
Error 404 The metadata value you specified no longer exists. The metadata server also returns this error if your metadata is deleted while you are waiting on a change.
Error 500 There was a temporary server error. Please retry your request.

Scheduled maintenance notice

The metadata server provides information about an instance's scheduling options and settings, through the scheduling/ directory and the maintenance-event attribute. You can use these attributes to learn about a virtual machine instance's scheduling options, and also use this information to notify you when a maintenance event is about to happen, specifically through the maintenance-event attribute.

The maintenance-event attribute changes its value to indicate the start and end of a maintenance event. The initial value of the attribute is NONE , which indicates that no maintenance event is starting. 60 seconds before a scheduled maintenance event, the maintenance-event value changes from NONE to MIGRATE_ON_HOST_MAINTENANCE . Throughout the duration of the maintenance event, the value remains the same. After the maintenance event ends, the value returns to NONE .

To query the maintenance-event attribute:

user@myinst:~$ curl

You can use the maintenance-event with the waiting for change feature to notify your scripts and applications when a maintenance event is about to start and end. This lets you automate any actions that you might want to run before or after the event. The following Python sample provides an example of how you might implement these two features together.

import httplib
import sys
import time
import urllib
import urllib2


class Error(Exception):

class UnexpectedStatusException(Error):

class UnexpectedMaintenanceEventException(Error):

def WatchMetadata(metadata_key, handler, initial_value=None):
  """Watches for a change in the value of metadata.

    metadata_key: The key identifying which metadata to watch for changes.
    handler: A callable to call when the metadata value changes. Will be passed
      a single parameter, the new value of the metadata.
    initial_value: The expected initial value for the metadata. The handler will
      not be called on the initial metadata request unless the value differs
      from this.

    UnexpectedStatusException: If the http request is unsuccessful for an
      unexpected reason.
  params = {
      'wait_for_change': 'true',
      'last_etag': 0,

  while True:
    value = initial_value
    # start a hanging-GET request for maintenance change events.
    url = '{base_url}{key}?{params}'.format(
    req = urllib2.Request(url, headers={'Metadata-Flavor': 'Google'})

      response = urllib2.urlopen(req)
      content =
      status = response.getcode()
    except urllib2.HTTPError as e:
      content = None
      status = e.code

    if status == httplib.SERVICE_UNAVAILABLE:
    elif status == httplib.OK:
      # Extract new maintenance-event value and latest etag.
      new_value = content
      headers =
      params['last_etag'] = headers['ETag']
      raise UnexpectedStatusException(status)

    # If the maintenance value changed, call the appropriate handler.
    if value != new_value:
      value = new_value

def HandleMaintenance(on_maintenance_start, on_maintenance_end):
  """Watches for and responds to maintenance-event status changes.

    on_maintenance_start: a callable to call before host maintenance starts.
    on_maintenance_end: a callable to call after host maintenance ends.

    UnexpectedStatusException: If the http request is unsuccessful for an
      unexpected reason.
    UnexpectedMaintenanceEventException: If the maintenance-event value is

  Note: Instances that are set to TERMINATE_ON_HOST_MAINTENANCE will receive
  a power-button push and will not be notified through this script.
  maintenance_key = 'instance/maintenance-event'

  def Handler(event):
    elif event == 'NONE':
      raise UnexpectedMaintenanceEventException(event)

  WatchMetadata(maintenance_key, Handler, initial_value='NONE')

def OnMaintenanceStart():
  # Add commands to perform before maintenance starts here.

def OnMaintenanceEnd():
  # Add commands to perform after maintenance is complete here.

if __name__ == '__main__':
  # Perform actions when maintenance events occur.
  HandleMaintenance(OnMaintenanceStart, OnMaintenanceEnd)

  # An example of watching for changes in a different metadata field.
  # Replace 'foo' with an existing custom metadata key of your choice.
  # WatchMetadata('instance/attributes/foo',
  #               lambda val: sys.stdout.write('%s\n' % val))

Transitioning to v1

The v1 metadata server functions slightly differently that the previous v1beta1 server. Here are some of the changes that need to be made for the new metadata server:

  • Update metadata requests to include the Metadata-Flavor: Google header

    The new metadata server requires that all requests provide the Metadata-Flavor: Google header, which indicates that the request was made with the intention of retrieving metadata values, Update your requests to include this new header. For example, a request to the disks/ attribute now looks like the following:

    user@myinst:~$ curl "" -H "Metadata-Flavor: Google"
  • Update requests that use the header X-Forwarded-For header

    These requests are automatically rejected by the server, as it generally indicates that the requests are proxied. Update your requests so they do not contain this header.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.