Yandex Cloud
Search
Discuss with expertTry it for free
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
  • Marketplace
    • Featured
    • Infrastructure & Network
    • Data Platform
    • AI for business
    • Security
    • DevOps tools
    • Serverless
    • Monitoring & Resources
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Center for Technologies and Society
    • Yandex Cloud Partner program
    • Price calculator
    • Pricing plans
  • Customer Stories
  • Documentation
  • Blog
© 2026 Direct Cursus Technology L.L.C.
Yandex Object Storage
    • All tutorials
    • Getting statistics on object queries with S3 Select
    • Getting website traffic statistics with S3 Select
    • Getting statistics on object queries using Yandex Query
    • Cost analysis by resource
    • Server-side encryption
    • Blue-green and canary deployment of service versions
    • Analyzing logs in DataLens
    • Mounting buckets to Yandex Data Processing host filesystems
    • Using Object Storage in Yandex Data Processing
    • Importing, processing, and exporting Object Storage data to Managed Service for ClickHouse®
    • Connecting a bucket as a disk in Windows
    • Migrating data from Yandex Data Streams using Yandex Data Transfer
    • Using hybrid storage in Yandex Managed Service for ClickHouse®
    • Loading data from Yandex Managed Service for OpenSearch to Yandex Object Storage using Yandex Data Transfer
    • Automatically copying objects from one bucket to another
    • Regular asynchronous recognition of audio files in a bucket
    • Training a model in Yandex DataSphere on data from Object Storage
    • Connecting to Object Storage from VPC
    • Migrating data to Yandex Managed Service for PostgreSQL using Yandex Data Transfer
    • Uploading data to Yandex MPP Analytics for PostgreSQL using Yandex Data Transfer
    • Uploading data to Yandex Managed Service for ClickHouse® using Yandex Data Transfer
    • Uploading data to Yandex Managed Service for YDB using Yandex Data Transfer
    • Exchanging data between Yandex Managed Service for ClickHouse® and Yandex Data Processing
    • Uploading data from Yandex Managed Service for YDB using Yandex Data Transfer
    • Hosting a static Gatsby website in Object Storage
    • Installing WordPress High Availability using Cloud Apps
    • Installing WordPress using Cloud Apps
    • Installing Ghost CMS High Availability using Cloud Apps
    • Migrating a database from Managed Service for PostgreSQL to Object Storage
    • Exchanging data between Yandex Managed Service for ClickHouse® and Yandex Data Processing
    • Importing data from Yandex Managed Service for PostgreSQL to Yandex Data Processing using Sqoop
    • Importing data from Yandex Managed Service for MySQL® to Yandex Data Processing using Sqoop
    • Migrating data from Yandex Object Storage to Yandex Managed Service for MySQL® using Yandex Data Transfer
    • Migrating a database from Yandex Managed Service for MySQL® to Yandex Object Storage
    • Exporting Greenplum® data to a cold storage in Yandex Object Storage
    • Loading data from Yandex Direct to a Yandex Managed Service for ClickHouse® data mart using Yandex Cloud Functions, Yandex Object Storage, and Yandex Data Transfer
    • Uploading Terraform states to Object Storage
    • Locking Terraform states using Managed Service for YDB
    • Visualizing Yandex Query data
    • Publishing game updates
    • Developing a custom integration in API Gateway
      • Overview
      • Management console
      • Terraform
    • Storing application runtime logs
    • Building a skill for Alice and a website with authorization
    • Building an interactive serverless application using WebSocket
    • Deploying a web application using the Java Servlet API
    • Developing a Telegram bot
    • Replicating logs to Object Storage using Fluent Bit
    • Replicating logs to Object Storage using Data Streams
    • Uploading audit logs to ArcSight SIEM
    • Uploading audit logs to Splunk SIEM
    • Creating an MLFlow server for logging experiments and artifacts
    • Operations with data in Yandex Query
    • Federated data queries using Query
    • Recognizing text in image archives using Vision OCR
    • Scheduled image and PDF recognition in an Object Storage bucket
    • Automating tasks using Managed Service for Apache Airflow™
    • Processing files with usage details in Yandex Cloud Billing
    • Deploying a web app with JWT authorization in API Gateway and authentication in Firebase
    • Searching for Yandex Cloud events in Yandex Query
    • Searching for Yandex Cloud events in Object Storage
    • Creating an external table from a bucket table using a configuration file
    • Migrating databases from Google BigQuery to Managed Service for ClickHouse®
    • Using Object Storage in Yandex Managed Service for Apache Spark™
  • Pricing policy
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Bucket logs
  • Release notes
  • FAQ

In this article:

  • Get your cloud ready
  • Required paid resources
  • Set up hosting for the URL shortener page
  • Create a service account
  • Create a database in Managed Service for YDB
  • Set up a function in Cloud Functions
  • Publish your URL shortener via API Gateway
  • Test the URL shortener
  • How to delete the resources you created
  1. Tutorials
  2. URL shortener
  3. Management console

Link shortener with the help of the management console

Written by
Yandex Cloud
Updated at May 28, 2026
  • Get your cloud ready
    • Required paid resources
  • Set up hosting for the URL shortener page
  • Create a service account
  • Create a database in Managed Service for YDB
  • Set up a function in Cloud Functions
  • Publish your URL shortener via API Gateway
  • Test the URL shortener
  • How to delete the resources you created

To create a link shortener using the Yandex Cloud management console:

  1. Get your cloud ready.
  2. Set up hosting for the URL shortener page.
  3. Create a service account.
  4. Create a database in Yandex Managed Service for YDB.
  5. Set up a function in Yandex Cloud Functions.
  6. Publish your URL shortener via Yandex API Gateway.
  7. Test the URL shortener.

If you no longer need the resources you created, delete them.

Get your cloud readyGet your cloud ready

Sign up for Yandex Cloud and create a billing account:

  1. Navigate to the management console and log in to Yandex Cloud or create a new account.
  2. On the Yandex Cloud Billing page, make sure you have a billing account linked and it has the ACTIVE or TRIAL_ACTIVE status. If you do not have a billing account, create one and link a cloud to it.

If you have an active billing account, you can create or select a folder for your infrastructure on the cloud page.

Learn more about clouds and folders here.

Required paid resourcesRequired paid resources

The infrastructure support cost for the URL shortener includes:

  • Fee for data storage (see Yandex Object Storage pricing).
  • Fee for YDB database operations and data storage (see Managed Service for YDB pricing).
  • Fee for the number of function calls, computing resources allocated to run the function, and outgoing traffic (see Cloud Functions pricing).
  • Fee for the number of requests to the API gateway and outgoing traffic (see API Gateway pricing).

Set up hosting for the URL shortener pageSet up hosting for the URL shortener page

To create a bucket, upload your URL shortener's HTML page to it, and configure it for static website hosting:

Management console
  1. In the management console, select your working folder.

  2. Select Object Storage.

  3. Click Create bucket.

  4. On the bucket creation page:

    1. Enter a name for the bucket.

      Warning

      Bucket names are unique throughout Object Storage, which means you cannot create two buckets with the same name, even in different folders belonging to different clouds.

    2. Set the maximum size to 1 GB.

    3. Set object read access to For all.

    4. Click Create bucket to complete the operation.

  5. Copy the HTML code and paste it into index.html:

    HTML code
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>URL shortener</title>
      <!-- warns against sending unnecessary GET requests to /favicon.ico -->
      <link rel="icon" href="data:;base64,iVBORw0KGgo=">
    </head>
    
    <body>
      <h1>Welcome</h1>
      <form action="javascript:shorten()">
        <label for="url">Enter a link:</label><br>
        <input id="url" name="url" type="text"><br>
        <input type="submit" value="Shorten">
      </form>
      <p id="shortened"></p>
    </body>
    
    <script>
      function shorten() {
        const link = document.getElementById("url").value
        fetch("/shorten", {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: link
        })
        .then(response => response.json())
        .then(data => {
          const url = data.url
          document.getElementById("shortened").innerHTML = `<a href=${url}>${url}</a>`
        })
        .catch(error => {
          document.getElementById("shortened").innerHTML = `<p>${error} occurred. Try again.</p>`
        })
      }
    </script>
    
    </html>
    
  6. Click the name of the bucket you created.

  7. Click Upload objects.

  8. Specify the index.html file you set up earlier.

  9. Click Upload.

  10. In the left-hand panel, select the Website tab.

  11. Select Hosting.

  12. Specify the website's home page: index.html.

  13. Click Save.

Create a service accountCreate a service account

To create a service account to enable interaction between the shortener components:

Management console
  1. Navigate to your working folder.

  2. Go to Identity and Access Management.

  3. Click Create service account.

  4. Enter a name for the service account: serverless-shortener.

  5. Click Add role and select editor.

  6. Click Create.

  7. Click the name of the service account you created.

    Save the service account ID, as you will need it later.

Create a database in Managed Service for YDBCreate a database in Managed Service for YDB

To create a database in Managed Service for YDB and configure it to store URLs:

Management console
  1. Navigate to your working folder.

  2. In the list of services, select Managed Service for YDB.

  3. Click Create a database.

  4. Enter the database name: for-serverless-shortener.

  5. Select Serverless as the database type.

  6. Click Create a database.

  7. Wait for the database to start.

    While being created, your database will have the Provisioning status. Once it is ready for use, its status will change to Running.

  8. Click the database name.

    Save the Endpoint field value, as you will need it later.

  9. In the left-hand panel, select the Navigation tab.

  10. Select Create → Table on the right side of the page.

  11. Configure the table:

    • Name tables: links.
    • Table type: Row table.
  12. Add these columns:

    • Column name: id; data type: Utf8. Set Primary key.
    • Column name: link; data type: Utf8.
  13. Click Create table.

Set up a function in Cloud FunctionsSet up a function in Cloud Functions

To create and set up a URL shortening function:

Management console
  1. Navigate to your working folder.

  2. In the list of services, select Cloud Functions.

  3. Click Create function.

  4. Enter the name: for-serverless-shortener.

  5. Click Create.

  6. From the Python drop-down list, select the python312 runtime environment.

  7. Click Continue.

  8. Copy the function code and paste it into index.py under Function code.

    Function code
    import ydb
    import urllib.parse
    import hashlib
    import base64
    import json
    import os
    import traceback
    
    def decode(event, body):
        is_base64_encoded = event.get('isBase64Encoded')
        if is_base64_encoded:
            body = str(base64.b64decode(body), 'utf-8')
        return body
    
    def response(statusCode, headers, isBase64Encoded, body):
        # Always returning string to body
        if not isinstance(body, str):
            body = json.dumps(body, ensure_ascii=False)
        return {
            'statusCode': statusCode,
            'headers': headers,
            'isBase64Encoded': isBase64Encoded,
            'body': body,
        }
    
    def get_config():
        endpoint = os.getenv("endpoint")
        database = os.getenv("database")
        if endpoint is None or database is None:
            raise AssertionError("You need to specify both environment variables: endpoint and database")
        credentials = ydb.iam.MetadataUrlCredentials()
        return ydb.DriverConfig(endpoint, database, credentials=credentials)
    
    def execute(config, query, params):
        with ydb.Driver(config) as driver:
            try:
                driver.wait(timeout=5, fail_fast=True)
            except Exception as e:
                print("Connect failed to YDB:", e)
                print(driver.discovery_debug_details())
                raise
    
            session = driver.table_client.session().create()
            prepared_query = session.prepare(query)
            return session.transaction(ydb.SerializableReadWrite()).execute(
                prepared_query,
                params,
                commit_tx=True
            )
    
    def insert_link(id, link):
        config = get_config()
        query = """
        DECLARE $id AS Utf8;
        DECLARE $link AS Utf8;
    
        UPSERT INTO links (id, link) VALUES ($id, $link);
        """
        params = {'$id': id, '$link': link}
        execute(config, query, params)
    
    def find_link(id):
        config = get_config()
        query = """
        DECLARE $id AS Utf8;
    
        SELECT link FROM links where id=$id;
        """
        params = {'$id': id}
        result_set = execute(config, query, params)
    
        if not result_set or not result_set[0].rows:
            return None
    
        # Paying attention to the structure of the result from ydb
        return result_set[0].rows[0].link
    
    def shorten(event):
        try:
            body = event.get('body')
            if body is None:
                return response(400, {'Content-Type': 'application/json'}, False,
                                {'error': 'No body in the request body'})
    
            body = decode(event, body)
    
            # Attempting to parse JSON with a url key; otherwise, treating body as a plain string
            url_value = None
            try:
                parsed = json.loads(body)
                if isinstance(parsed, dict):
                    url_value = parsed.get('url')
                else:
                    # If not a JSON object is sent, ignoring
                    url_value = None
            except Exception:
                # If body is not JSON, treating it as plain URL
                url_value = body
    
            if not url_value:
                return response(400, {'Content-Type': 'application/json'}, False,
                                {'error': 'The url parameter was expected in the request body'})
    
            # Cleaning the URL from eventual coded characters
            clean_url = urllib.parse.unquote(url_value).strip()
            if not clean_url:
                return response(400, {'Content-Type': 'application/json'}, False,
                                {'error': 'Empty url'})
    
            link_id = hashlib.sha256(clean_url.encode('utf8')).hexdigest()[:6]
            insert_link(link_id, clean_url)
    
            # Returning the relative path; the frontend will add the origin by themselves
            return response(200, {'Content-Type': 'application/json'}, False,
                            {'url': f'/r/{link_id}'})
        except Exception as e:
            print("Exception in shorten():", e)
            traceback.print_exc()
            return response(500, {'Content-Type': 'application/json'}, False,
                            {'error': 'internal server error'})
    
    def redirect(event):
        try:
            # Securely retrieving path params
            path_params = event.get('pathParams') or event.get('pathParameters') or {}
            link_id = path_params.get('id')
            if not link_id:
                # Probably, the full path was received in event['url'] or ['path']
                url = event.get('url') or event.get('path') or ''
                if url and url.startswith('/r/'):
                    link_id = url.split('/r/')[-1].split('?')[0]
    
            if not link_id:
                return response(400, {'Content-Type': 'application/json'}, False, {'error': 'No ID'})
    
            redirect_to = find_link(link_id)
    
            if redirect_to:
                return response(302, {'Location': redirect_to}, False, '')
            return response(404, {'Content-Type': 'application/json'}, False, {'error': 'The link does not exist'})
        except Exception as e:
            print("Exception in redirect():", e)
            traceback.print_exc()
            return response(500, {'Content-Type': 'application/json'}, False, {'error': 'internal server error'})
    
    def get_result(url, event):
        if url == "/shorten" or url.startswith("/shorten"):
            return shorten(event)
        if url.startswith("/r/"):
            return redirect(event)
        return response(404, {'Content-Type': 'application/json'}, False, {'error': 'The path does not exist'})
    
    def handler(event, context):
        url = event.get('url') or event.get('path') or ''
        if url:
            # Sometimes, the URL from the gateway comes with a question mark at the end
            if url.endswith('?'):
                url = url[:-1]
            return get_result(url, event)
        return response(404, {'Content-Type': 'application/json'}, False, {'error': 'The function must be called via API Gateway.'})
    
  9. Under Function code, create a file named requirements.txt and paste the following text into it:

    ydb
    
  10. Specify the entry point: index.handler.

  11. Set the timeout to 5.

  12. Select the serverless-shortener service account.

  13. Add these environment variables:

    • endpoint: Enter the first part of the previously saved Endpoint field value (preceding /?database=), e.g., grpcs://ydb.serverless.yandexcloud.net:2135.
    • database: Enter the second part of the previously saved Endpoint field value (following /?database=), e.g., /ru-central1/r1gra875baom********/g5n22e7ejfr1********.
  14. Click Save changes.

  15. Under Overview, enable Public function.

Save the function ID, as you will need it later.

Publish your URL shortener via API GatewayPublish your URL shortener via API Gateway

To publish your URL shortener via API Gateway:

Management console
  1. Navigate to your working folder.

  2. From the list of services, select API Gateway.

  3. Click Create API gateway.

  4. In the Name field, enter for-serverless-shortener.

  5. Copy and paste the following code under Specification:

    API gateway specification
    openapi: 3.0.0
    info:
      title: for-serverless-shortener
      version: 1.0.0
    paths:
      /:
        get:
          x-yc-apigateway-integration:
            type: object_storage
            bucket: <bucket_name>#<-- bucket name
            object: index.html # <-- HTML file name
            presigned_redirect: false
            service_account: <service_account_id> # <-- service_account_ID
          operationId: static
      /shorten:
        post:
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: <function_id> # <-- function ID
          operationId: shorten
      /r/{id}:
        get:
          x-yc-apigateway-integration:
            type: cloud_functions
            function_id: <function_id> # <-- function ID
          operationId: redirect
          parameters:
          - description: id of the url
            explode: false
            in: path
            name: id
            required: true
            schema:
              type: string
            style: simple
    

    Edit the specification code as follows:

    • Replace <service_account_id> with the ID of the service account you created.
    • Replace <function_id> with the ID of the function you created.
    • Replace <bucket_name> with the name of the bucket you created.
  6. Click Create.

  7. Click the name of the API gateway you created.

  8. Copy the url value from the specification.

    Use this URL to test the URL shortener.

Test the URL shortenerTest the URL shortener

To make sure your shortener components interact properly:

  1. In your browser, open the previously copied shortener URL.

  2. In the input field, enter the URL you want to shorten.

  3. Click Shorten.

    You will see the shortened URL below.

  4. Open the shortened URL. It should lead to the same page as the original link.

How to delete the resources you createdHow to delete the resources you created

To stop incurring charges for the resources you created:

  1. Delete for-serverless-shortener.
  2. Delete the function in for-serverless-shortener.
  3. Delete the for-serverless-shortener YDB database.
  4. Delete the bucket.

See alsoSee also

  • URL shortener with the help of Terraform

Was the article helpful?

Previous
Overview
Next
Terraform
© 2026 Direct Cursus Technology L.L.C.