Managing object custom metadata
When uploading an object to Object Storage, you can provide custom metadata in the form of key-value
pairs.
Uploading an object with metadata
If you do not have the Yandex Cloud CLI yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID>
command. You can also set a different folder for any specific command using the --folder-name
or --folder-id
parameter.
-
See the description of the CLI command for uploading an object:
yc storage s3api put-object --help
-
Get a list of buckets in the default folder:
yc storage bucket list
Result:
+------------------+----------------------+-------------+-----------------------+---------------------+ | NAME | FOLDER ID | MAX SIZE | DEFAULT STORAGE CLASS | CREATED AT | +------------------+----------------------+-------------+-----------------------+---------------------+ | first-bucket | b1gmit33ngp6******** | 53687091200 | STANDARD | 2022-12-16 13:58:18 | +------------------+----------------------+-------------+-----------------------+---------------------+
-
Run this command:
yc storage s3api put-object \ --bucket <bucket_name> \ --key <object_key> \ --body <local_file_path> \ --metadata "<key_1>"="<value_1>","<key_2>"="<value_2>"
Where:
--bucket
: Name of the bucket you want to upload the object to.--key
: Bucket object key.--body
: Path to the local file you want to upload to the bucket.--metadata
: Custom metadata provided as comma-separatedkey-value
pairs. Keys must only consist of ASCII characters . The value cannot exceed 2 KB.
Result:
etag: '"65187664ed291179f9244d61********"' request_id: 3eca0fd2********
If you do not have the AWS CLI yet, install and configure it.
In the terminal, run this command:
aws s3api put-object \
--bucket <bucket_name> \
--key <object_key> \
--body <local_file_path> \
--metadata "<key_1>"="<value_1>","<key_2>"="<value_2>" \
--endpoint-url=https://storage.yandexcloud.net
Where:
--bucket
: Name of the bucket you want to upload the object to.--key
: Bucket object key.--body
: Path to the local file you want to upload to the bucket.--metadata
: Custom metadata provided as comma-separatedkey-value
pairs. Keys must only consist of ASCII characters . The value cannot exceed 2 KB.--endpoint-url
: Object Storage endpoint.
Result:
{
"ETag": "\"65187664ed291179f9244d61********\""
}
Getting object metadata
If you do not have the Yandex Cloud CLI yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID>
command. You can also set a different folder for any specific command using the --folder-name
or --folder-id
parameter.
-
See the description of the CLI command for getting object metadata:
yc storage s3api head-object --help
-
Get a list of buckets in the default folder:
yc storage bucket list
Result:
+------------------+----------------------+-------------+-----------------------+---------------------+ | NAME | FOLDER ID | MAX SIZE | DEFAULT STORAGE CLASS | CREATED AT | +------------------+----------------------+-------------+-----------------------+---------------------+ | first-bucket | b1gmit33ngp6******** | 53687091200 | STANDARD | 2022-12-16 13:58:18 | +------------------+----------------------+-------------+-----------------------+---------------------+
-
Get a list of objects in the bucket:
yc storage s3api list-objects \ --bucket <bucket_name>
Result:
contents: - key: object-1.txt last_modified: "2025-04-28T11:04:42.796Z" etag: '"e807f1fcf82d132f9bb018ca********"' size: "10" owner: id: aje9k8luj4qf******** display_name: aje9k8luj4qf******** storage_class: STANDARD ... name: first-bucket max_keys: "1000" key_count: "9" request_id: 8e85efa1********
-
Run this command:
yc storage s3api head-object \ --bucket <bucket_name> \ --key <object_key>
Where:
--bucket
: Name of the bucket containing the object.--key
: Bucket object key.
Result:
etag: '"d41d8cd98f00b204e9800998********"' request_id: 6428ce25******** accept_ranges: bytes content_type: application/octet-stream last_modified_at: "2024-10-08T12:36:36Z" server_side_encryption: aws:kms sse_kms_key_id: abj497vtg3h0********
If you do not have the AWS CLI yet, install and configure it.
In the terminal, run this command:
aws s3api head-object \
--bucket <bucket_name> \
--key <object_key> \
--endpoint-url=https://storage.yandexcloud.net
Where:
--bucket
: Name of the bucket containing the object.--key
: Bucket object key.--endpoint-url
: Object Storage endpoint.
Result:
{
"AcceptRanges": "bytes",
"LastModified": "2025-04-28T11:47:10+00:00",
"ContentLength": 812,
"ETag": "\"65187664ed291179f9244d61********\"",
"ContentType": "application/octet-stream",
"Metadata": {
"Key1": "val1",
"Key2": "val2"
}
}
Use the getObjectMeta S3 API method, e.g., via curl
.
Use curl
8.3.0
AWS_KEY_ID="<static_key_ID>"
AWS_SECRET_KEY="<secret_key>"
BUCKET_NAME="<bucket_name>"
OBJECT_PATH="<object_key>"
curl \
--head \
--user "${AWS_KEY_ID}:${AWS_SECRET_KEY}" \
--aws-sigv4 "aws:amz:ru-central1:s3" \
"https://storage.yandexcloud.net/${BUCKET_NAME}/${OBJECT_PATH}"
Where:
AWS_KEY_ID
: Static access key ID.AWS_SECRET_KEY
: Secret key.BUCKET_NAME
: Name of the bucket containing the object.OBJECT_PATH
: Bucket object key.
Updating object metadata
Warning
The existing custom metadata will be completely overwritten by the new metadata.
If you do not have the Yandex Cloud CLI yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID>
command. You can also set a different folder for any specific command using the --folder-name
or --folder-id
parameter.
-
See the description of the CLI command to copy an object:
yc storage s3api copy-object --help
-
Get a list of buckets in the default folder:
yc storage bucket list
Result:
+------------------+----------------------+-------------+-----------------------+---------------------+ | NAME | FOLDER ID | MAX SIZE | DEFAULT STORAGE CLASS | CREATED AT | +------------------+----------------------+-------------+-----------------------+---------------------+ | first-bucket | b1gmit33ngp6******** | 53687091200 | STANDARD | 2022-12-16 13:58:18 | +------------------+----------------------+-------------+-----------------------+---------------------+
-
Get a list of objects in the bucket:
yc storage s3api list-objects \ --bucket <bucket_name>
Result:
contents: - key: object-1.txt last_modified: "2025-04-28T11:04:42.796Z" etag: '"e807f1fcf82d132f9bb018ca********"' size: "10" owner: id: aje9k8luj4qf******** display_name: aje9k8luj4qf******** storage_class: STANDARD ... name: first-bucket max_keys: "1000" key_count: "9" request_id: 8e85efa1********
-
Run this command:
yc storage s3api copy-object \ --bucket <bucket_name> \ --key <object_key> \ --copy-source <bucket_name>/<object_key> \ --metadata "<key_1>"="<value_1>","<key_2>"="<value_2>" \ --metadata-directive REPLACE
Where:
--bucket
: Name of the bucket where you want to update the object metadata.--key
: Bucket object key.--copy-source
: Path to the object in<bucket_name>/<object_key>
format.--metadata
: New custom metadata provided as comma-separatedkey-value
pairs. Keys must only consist of ASCII characters . The value cannot exceed 2 KB.--metadata-directive
: Parameter specifying the need to overwrite the object metadata with new metadata.
Result:
copy_object_result: etag: '"65187664ed291179f9244d61********"' last_modified_at: "2025-04-28T11:47:10.351Z" request_id: 8b7e94df******** copy_source_version_id: "null"
If you do not have the AWS CLI yet, install and configure it.
In the terminal, run this command:
aws s3api copy-object \
--bucket <bucket_name> \
--key <object_key> \
--copy-source <bucket_name>/<object_key> \
--metadata "<key_1>"="<value_1>","<key_2>"="<value_2>" \
--metadata-directive REPLACE \
--endpoint-url=https://storage.yandexcloud.net
Where:
--bucket
: Name of the bucket where you want to update the object metadata.--key
: Bucket object key.--copy-source
: Path to the object in<bucket_name>/<object_key>
format.--metadata
: New custom metadata provided as comma-separatedkey-value
pairs. Keys must only consist of ASCII characters . The value cannot exceed 2 KB.--metadata-directive
: Parameter specifying the need to overwrite the object metadata with new metadata.--endpoint-url
: Object Storage endpoint.
Result:
{
"CopySourceVersionId": "null",
"CopyObjectResult": {
"ETag": "\"65187664ed291179f9244d61********\"",
"LastModified": "2025-04-28T11:47:10.351000+00:00"
}
}
Use the copy S3 API method, e.g., via curl
.
Use curl
8.3.0
AWS_KEY_ID="<static_key_ID>"
AWS_SECRET_KEY="<secret_key>"
BUCKET_NAME="<bucket_name>"
OBJECT_PATH="<object_key>"
META_KEY_1="<key_1>"
META_VALUE_1="<value_1>"
META_KEY_2="<key_2>"
META_VALUE_2="<value_2>"
curl \
--request PUT \
--user "${AWS_KEY_ID}:${AWS_SECRET_KEY}" \
--aws-sigv4 "aws:amz:ru-central1:s3" \
--header "X-Amz-Copy-Source: /${BUCKET_NAME}/${OBJECT_PATH}" \
--header "X-Amz-Metadata-Directive: REPLACE" \
--header "X-Amz-Meta-${META_KEY_1}: ${META_VALUE_1}" \
--header "X-Amz-Meta-${META_KEY_2}: ${META_VALUE_2}" \
--verbose \
"https://storage.yandexcloud.net/${BUCKET_NAME}/${OBJECT_PATH}"
Where:
AWS_KEY_ID
: Static access key ID.AWS_SECRET_KEY
: Secret key.BUCKET_NAME
: Name of the bucket where you want to update the object metadata.OBJECT_PATH
: Bucket object key.META_KEY_1
andMETA_KEY_1
: New custom metadata keys. Keys must only consist of ASCII characters .META_VALUE_1
andMETA_VALUE_2
: New custom metadata values. The value cannot exceed 2 KB.
Metadata searching
Note
For metadata searching, use the LIST
and HEAD
operations. These operations are not free of charge.
If you do not have the Yandex Cloud CLI yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID>
command. You can also set a different folder for any specific command using the --folder-name
or --folder-id
parameter.
The Yandex Cloud CLI offers no built-in function to search objects directly by metadata. However, you can run a bash script to check the metadata of each object in the bucket one by one.
-
Save your search data to these variables:
BUCKET_NAME=<bucket_name> METADATA_KEY=<metadata_key> METADATA_VALUE=<metadata_value>
-
Run this command:
# Going over all objects and checking their metadata yc storage s3api list-objects \ --bucket $BUCKET_NAME \ --format json | jq -r '.contents[].key' | while read -r key; do # Getting object metadata metadata=$(yc storage s3api head-object --bucket $BUCKET_NAME --key "$key" --format json) # Checking for the right key and the metadata value if echo "$metadata" | jq -e ".metadata[\"$METADATA_KEY\"] == \"$METADATA_VALUE\"" > /dev/null; then echo "Found an object with required metadata: $key" echo "$metadata" | jq echo "----------------------------------------" fi done
Result:
Found an object with required metadata: ********.jpg { "etag": "\"d658ade1b7628f5fa824c60a********\"", "request_id": "8dcb3cfb********", "accept_ranges": "bytes", "content_length": "223840", "content_type": "application/octet-stream", "last_modified_at": "2025-04-23T10:54:16Z", "metadata": { "key1": "val1", "key2": "val2" } } ----------------------------------------
If you do not have the AWS CLI yet, install and configure it.
The AWS CLI offers no built-in function to search for objects directly by metadata. However, you can run a bash script to check the metadata of each object in the bucket one by one.
-
Save your search data to these variables:
BUCKET_NAME=<bucket_name> METADATA_KEY=<metadata_key> METADATA_VALUE=<metadata_value>
-
Run this command:
# Going over all objects and checking their metadata aws s3api list-objects \ --bucket $BUCKET_NAME \ --endpoint-url=https://storage.yandexcloud.net \ --query 'Contents[].Key' \ --output text | tr '\t' '\n' | while read -r key; do # Getting object metadata metadata=$(aws s3api head-object \ --bucket $BUCKET_NAME \ --key "$key" \ --endpoint-url=https://storage.yandexcloud.net) # Converting METADATA_KEY to uppercase uppercase_threshold_key=$(echo "$METADATA_KEY" | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2))}') # Checking for the right key and the metadata value echo "$metadata" | jq -e --arg key "$uppercase_threshold_key" --arg value "$METADATA_VALUE" '.Metadata[$key] == $value' > /dev/null if [ $? -eq 0 ]; then echo "Found an object with required metadata: $key" echo "$metadata" | jq echo "----------------------------------------" fi done
Result:
Found an object with required metadata: ********.jpg { "AcceptRanges": "bytes", "LastModified": "Wed, 23 Apr 2025 10:54:16 GMT", "ContentLength": 223840, "ETag": "\"d658ade1b7628f5fa824c60a********\"", "ContentType": "application/octet-stream", "Metadata": { "Key1": "val1", "Key2": "val2" } } ----------------------------------------
You can search for objects by metadata using boto3 for Python.
-
Create a file named
main.py
with this code:import boto3 import sys import json from datetime import datetime def format_response(response, obj_name): # Converting the date to the required format last_modified = response['LastModified'].strftime("%a, %d %b %Y %H:%M:%S GMT") formatted_response = { "RequestId": response['ResponseMetadata']['RequestId'], "AcceptRanges": response['AcceptRanges'], "LastModified": last_modified, "ContentLength": response['ContentLength'], "ETag": response['ETag'], "ContentType": response['ContentType'], "Metadata": response['Metadata'] } # Formatted output with indentations formatted_output = json.dumps(formatted_response, indent=2, ensure_ascii=False) print(f"Found an object with required metadata: {obj_name}") print(formatted_output) print("----------------------------------------") def update_object_metadata(bucket_name, metadata_key, metadata_value): s3 = boto3.client('s3') obj_names = [] try: # Getting a list of objects paginator = s3.get_paginator('list_objects_v2') for page in paginator.paginate(Bucket=bucket_name): for obj in page.get('Contents', []): obj_names.append(obj['Key']) except Exception as e: print(f"Error getting the list of objects: {e}") return found = False for obj_name in obj_names: try: # Getting current metadata for the object response = s3.head_object(Bucket=bucket_name, Key=obj_name) current_metadata = response.get('Metadata', {}) # Normalizing metadata for comparison purposes normalized_key = metadata_key.lower() # Converting metadata to lowercase normalized_metadata = {key.lower(): value for key, value in current_metadata.items()} # Checking for a match if normalized_metadata.get(normalized_key) == metadata_value: format_response(response, obj_name) found = True except s3.exceptions.ClientError as e: print(f"Error getting metadata for the {obj_name} object: {e}") continue if not found: print('There are no objects with the specified metadata in the bucket.') if __name__ == "__main__": if len(sys.argv) != 4: print("Using: python main.py metadata_key metadata_value bucket_name") sys.exit(1) metadata_key = sys.argv[1] metadata_value = sys.argv[2] bucket_name = sys.argv[3] update_object_metadata(bucket_name, metadata_key, metadata_value)
-
Run the script with your values specified:
python main.py <metadata_key> <metadata_value> <bucket_name>
Result:
Found an object with required metadata: ********.jpg { "AcceptRanges": "bytes", "LastModified": "Wed, 23 Apr 2025 10:54:16 GMT", "ContentLength": 223840, "ETag": "\"d658ade1b7628f5fa824c60a********\"", "ContentType": "application/octet-stream", "Metadata": { "Key1": "val1", "Key2": "val2" } } ----------------------------------------
If an object with the specified metadata exists in the bucket, the terminal will display the information about that object.