All Products
Search
Document Center

Object Storage Service:Manage object metadata (OSS SDK for Python V2)

Last Updated:Mar 20, 2026

Object metadata describes an object stored in OSS. Each object has two categories of metadata: system-defined metadata and user-defined metadata.

  • System-defined metadata: Standard HTTP headers set by OSS or by you at upload time, such as Content-Type, Content-Disposition, Cache-Control, and Expires. Some fields are read-only (for example, Content-Length, ETag, and Last-Modified); others are writable.

  • User-defined metadata: Custom key-value pairs you attach to an object, prefixed with x-oss-meta- in the underlying API. Use these to store application-specific attributes alongside the object.

This topic shows how to set, query, and modify object metadata using OSS SDK for Python V2.

Prerequisites

Before you begin, ensure that you have:

The examples in this topic use the region ID cn-hangzhou. By default, a public endpoint is used. To access OSS from another Alibaba Cloud service in the same region, use an internal endpoint. For a full list of regions and endpoints, see Regions and endpoints.

Set metadata during upload

Pass metadata in PutObjectRequest. The example below sets user-defined metadata (key1, key2) on upload. The same approach applies to all other upload operations.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="put object sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    args = parser.parse_args()

    # Load credentials from environment variables.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    data = "Hello, OSS!".encode('utf-8')

    result = client.put_object(oss.PutObjectRequest(
        bucket=args.bucket,
        key=args.key,
        body=data,
        metadata={
            'key1': 'value1',
            'key2': 'value2'
        }
    ))

    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content md5: {result.content_md5},'
          f' etag: {result.etag},'
          f' hash crc64: {result.hash_crc64},'
          f' version id: {result.version_id},'
    )

if __name__ == "__main__":
    main()

Query object metadata

OSS provides two methods to retrieve metadata, depending on how much information you need.

MethodReturnsUse when
HeadObjectAll metadata (system-defined and user-defined)You need the full metadata set
GetObjectMetaSix fields only: Content-Length, ETag, Last-Modified, Last-Access-Time, version ID, and CRC-64 hashYou need a lightweight check without downloading the object body

Query all metadata with HeadObject

HeadObject returns all system-defined and user-defined metadata without downloading the object body.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="head object sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    result = client.head_object(oss.HeadObjectRequest(
        bucket=args.bucket,
        key=args.key,
    ))

    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content length: {result.content_length},'
          f' content type: {result.content_type},'
          f' etag: {result.etag},'
          f' last modified: {result.last_modified},'
          f' content md5: {result.content_md5},'
          f' cache control: {result.cache_control},'
          f' content disposition: {result.content_disposition},'
          f' content encoding: {result.content_encoding},'
          f' expires: {result.expires},'
          f' hash crc64: {result.hash_crc64},'
          f' storage class: {result.storage_class},'
          f' object type: {result.object_type},'
          f' version id: {result.version_id},'
          f' tagging count: {result.tagging_count},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' server side encryption key id: {result.server_side_encryption_key_id},'
          f' next append position: {result.next_append_position},'
          f' expiration: {result.expiration},'
          f' restore: {result.restore},'
          f' process status: {result.process_status},'
          f' request charged: {result.request_charged},'
          f' allow origin: {result.allow_origin},'
          f' allow methods: {result.allow_methods},'
          f' allow age: {result.allow_age},'
          f' allow headers: {result.allow_headers},'
          f' expose headers: {result.expose_headers},'
          )

if __name__ == "__main__":
    main()

Query partial metadata with GetObjectMeta

GetObjectMeta returns only six fields: Content-Length, ETag, Last-Modified, Last-Access-Time, version ID, and CRC-64 hash. Use this when you need a lightweight check and do not require the full header set.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="get object meta sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    result = client.get_object_meta(oss.GetObjectMetaRequest(
        bucket=args.bucket,
        key=args.key,
    ))

    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content length: {result.content_length},'
          f' etag: {result.etag},'
          f' last modified: {result.last_modified},'
          f' last access time: {result.last_access_time},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          )

if __name__ == "__main__":
    main()

Modify metadata of an existing object

To modify the metadata of an existing object, copy the object back to itself with metadata_directive='REPLACE' and supply the new metadata set.

OSS SDK for Python V2 provides two ways to copy an object with updated metadata:

  • `CopyObject`: Copies an object and replaces its metadata.

  • `Copier.Copy`: A higher-level client that handles both single-part and multipart copy automatically. Use this to overwrite all existing metadata with new metadata, remove original metadata, update only specified metadata headers, or optionally delete the source object after the copy completes.

Use CopyObject to replace metadata

The example below copies an object to itself with new metadata.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copy object sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the destination bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the destination object.', required=True)
parser.add_argument('--source_key', help='The name of the source object.', required=True)
parser.add_argument('--source_bucket', help='The name of the source bucket.', required=True)

def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    result = client.copy_object(oss.CopyObjectRequest(
        bucket=args.bucket,
        key=args.key,
        source_key=args.source_key,
        source_bucket=args.source_bucket,
        metadata={'key1': 'value1', 'key2': 'value2'},
        metadata_directive='REPLACE',  # Replace all metadata with the values above.
    ))

    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' source version id: {result.source_version_id},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' last modified: {result.last_modified},'
          f' etag: {result.etag},'
    )

if __name__ == "__main__":
    main()

Use Copier.Copy to replace metadata

Copier.Copy wraps the copy operation with automatic multipart support. Pass the same CopyObjectRequest with metadata_directive="REPLACE".

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copier sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)
parser.add_argument('--source_key', help='The name of the source address for object.', required=True)
parser.add_argument('--source_bucket', help='The name of the source address for bucket.', required=True)

def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    # Create a copier that handles both single-part and multipart copy.
    copier = client.copier()

    result = copier.copy(
        oss.CopyObjectRequest(
            bucket=args.bucket,
            key=args.key,
            source_bucket=args.source_bucket,
            source_key=args.source_key,
            metadata={'key1': 'value1', 'key2': 'value2'},
            metadata_directive="REPLACE",  # Replace all metadata with the values above.
        )
    )

    print(vars(result))

if __name__ == "__main__":
    main()

What's next