AWS CDK TypeScript to Python Converter

Paste a CDK v2 stack written in TypeScript and get the Python version: aws_cdk imports, self and snake_case keyword arguments. Construct IDs are copied exactly, so the synthesized template can match the stack you already deployed.

Your codeAWS CDK (TypeScript)
Drop the file to load it
Tab indents · Esc, Tab exits
ResultAWS CDK (Python)
Your AWS CDK (Python) will appear hereClick Convert to Python or press Ctrl Enter
stack.py
Don't paste secrets

How to convert a CDK app from TypeScript to Python

To convert an AWS CDK app from TypeScript to Python, paste one stack into the editor above and press Convert to Python. The converter rewrites imports as aws_cdk modules, turns new Construct(this, id, { props }) into Construct(self, id, prop=...) with snake_case names, and keeps every construct ID. Then run it from a Python CDK project and check cdk diff.

  1. Add your TypeScript stackPaste a stack into the AWS CDK (TypeScript) editor, use Open file for a .ts, .js or .txt file up to 500 KB, or drop a file onto the editor. Sample loads a stack with an SQS queue, a DynamoDB table and a Lambda worker.
  2. Let the secret check runBefore anything is sent, the page looks for AWS access keys, secret keys, private keys and common API tokens. If it finds one, it shows you where so you can replace it with a placeholder.
  3. Convert to PythonClick Convert to Python or press Ctrl + Enter. The Python code streams into the right-hand editor and you can stop it at any time. Each conversion takes up to 60,000 characters, which fits a typical stack file.
  4. Review the PythonCheck that every construct ID matches the original, and look for TODO: comments where a TypeScript-only pattern had no direct Python form. Then Copy the result or Download it as stack.py.
  5. Run it in a Python CDK projectCreate a virtual environment, run pip install aws-cdk-lib constructs, set the app command in cdk.json to python3 app.py, then run cdk diff against the deployed stack.
Four steps to move an AWS CDK stack from TypeScript to Python: paste the stack, convert it with construct IDs kept, run it from a Python app with python3 app.py, then check cdk diff for no differences
The migration in four steps. The last one, cdk diff, tells you whether anything would be replaced.

Why convert a CDK app from TypeScript to Python

Teams usually move a CDK app to Python so infrastructure code is written, reviewed and tested in the same language as the services it deploys. That's common for data, machine learning and Lambda-heavy teams whose application code is already Python. The CDK CLI still runs on Node.js, but your stacks, helper modules and tests all become Python.

Because every CDK construct is published to Python through jsii, this is a change of syntax, not of architecture. The same aws-cdk-lib classes exist in both languages, so a Python app that keeps the same stack names and construct IDs synthesizes the same CloudFormation template as the TypeScript app it replaces. That's what lets you switch languages without replacing deployed resources.

By hand, the work is slow and easy to get wrong: every prop is renamed, every import path changes, and one mistyped construct ID replaces a resource. The converter handles the mechanical part for a whole stack file, so your review can focus on IDs, custom constructs and tests. To go the other way, use the CDK Python to TypeScript converter.

Diagram showing aws-cdk-lib, written in TypeScript, published by jsii to npm for TypeScript and PyPI for Python, with both apps synthesizing the same CloudFormation template
jsii publishes the same construct library to both languages, so the template doesn't have to change.

What changes when CDK code moves to Python

The AWS CDK is written in TypeScript and published to Python through jsii, so the same constructs exist in both languages. The conversion is mostly syntax: new Table(this, "Orders", { partitionKey }) becomes dynamodb.Table(self, "Orders", partition_key=...), camelCase props become snake_case keyword arguments, and aws-cdk-lib/aws-lambda becomes aws_cdk.aws_lambda, imported under an alias such as lambda_ because lambda is a Python keyword.

The part that matters most for a deployed app is the construct IDs. CloudFormation logical IDs are built from each construct's ID and path, so if the Python app keeps the same stack names and construct IDs, deploying it updates the existing stack instead of replacing resources. cdk diff against the deployed stack should show no resource changes.

AWS's guide to working with the CDK in Python covers the virtual environment and the cdk.json app command for the new project.

A CDK TypeScript sqs.Queue call next to its Python version, showing this becoming self, camelCase props becoming snake_case keyword arguments, module imports changing and the OrderQueue construct ID staying the same
One construct call in both languages. Only the syntax changes; the construct ID doesn't.

CDK TypeScript vs Python: syntax reference

What each common TypeScript pattern looks like in a Python CDK app. The class and enum names don't change; the way you call and name things does.

AWS CDK TypeScript syntax compared with Python syntax
PatternTypeScriptPython
Import a moduleimport * as sqs from "aws-cdk-lib/aws-sqs"from aws_cdk import aws_sqs as sqs
Lambda moduleimport * as lambda from "aws-cdk-lib/aws-lambda"from aws_cdk import aws_lambda as lambda_
Create a constructnew sqs.Queue(this, "Jobs", { ... })sqs.Queue(self, "Jobs", ...)
PropsvisibilityTimeout: Duration.seconds(60)visibility_timeout=Duration.seconds(60)
Struct valuespartitionKey: { name: "id", type: AttributeType.STRING }partition_key=dynamodb.Attribute(name="id", type=dynamodb.AttributeType.STRING)
Methods and propertiestable.grantWriteData(fn), table.tableNametable.grant_write_data(fn), table.table_name
Static methodsCode.fromAsset("worker")Code.from_asset("worker")
EnumsRemovalPolicy.RETAINRemovalPolicy.RETAIN (unchanged)
Stack constructorconstructor(scope: Construct, id: string, props?: StackProps)def __init__(self, scope: Construct, construct_id: str, **kwargs)
Entry pointbin/app.ts, run with ts-nodeapp.py, run with python3 app.py and ending in app.synth()
TestsJest with Template.fromStack(stack)pytest with Template.from_stack(stack)

Key features

  • Imports mapped to aws_cdk modulesaws-cdk-lib/aws-* paths become from aws_cdk import aws_* imports, with an alias for aws_lambda because lambda is reserved in Python.
  • Props become keyword argumentsEach props object is spread into snake_case keyword arguments, and nested object literals become struct classes such as dynamodb.Attribute.
  • Methods and properties renamedgrantWriteData, tableName and fromAsset become grant_write_data, table_name and from_asset.
  • Construct IDs left aloneStack names and construct IDs are copied as written, so the construct tree and the logical IDs it produces stay the same.
  • Gaps are markedComments and structure carry over. Anything without a direct Python form gets a TODO: comment so it doesn't slip through review.
  • TypeScript or JavaScript inputOpen .ts or .js stack files. JavaScript CDK apps use the same construct calls, so they convert the same way.
  • Checked, streamed and downloadableKeys are detected in your browser before sending, the result streams in with a Stop button, and you can save it as stack.py.
  • Free, with no signupConvert straight away. A free account raises your limits and lists your recent conversions on your dashboard.

Examples: CDK TypeScript converted to Python

Three stacks where the Python version differs by more than casing. Choose Try this example to load the TypeScript into the converter. The Python shown is what correct output looks like; yours may be formatted differently.

S3 bucket with a lifecycle rule

Object literals inside a list, such as lifecycle rules, become struct classes like s3.LifecycleRule, and every prop is renamed to snake_case.

AWS CDK (TypeScript)
import { Stack, StackProps, Duration, RemovalPolicy } from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";

export class LogsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, "AccessLogs", {
      encryption: s3.BucketEncryption.S3_MANAGED,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      removalPolicy: RemovalPolicy.RETAIN,
      lifecycleRules: [
        { prefix: "raw/", expiration: Duration.days(30) },
      ],
    });
  }
}
AWS CDK (Python)
from aws_cdk import Stack, Duration, RemovalPolicy
from aws_cdk import aws_s3 as s3
from constructs import Construct


class LogsStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        s3.Bucket(
            self, "AccessLogs",
            encryption=s3.BucketEncryption.S3_MANAGED,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
            removal_policy=RemovalPolicy.RETAIN,
            lifecycle_rules=[
                s3.LifecycleRule(prefix="raw/", expiration=Duration.days(30)),
            ],
        )

Lambda function behind API Gateway

The lambda module gets an alias, TypeScript's shorthand { handler } becomes handler=handler, and true becomes True. The function's own runtime doesn't change.

AWS CDK (TypeScript)
import { Stack, StackProps, Duration } from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigw from "aws-cdk-lib/aws-apigateway";
import { Construct } from "constructs";

export class ApiStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const handler = new lambda.Function(this, "ApiHandler", {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: "index.handler",
      code: lambda.Code.fromAsset("lambda"),
      memorySize: 512,
      timeout: Duration.seconds(10),
    });

    new apigw.LambdaRestApi(this, "PublicApi", { handler, proxy: true });
  }
}
AWS CDK (Python)
from aws_cdk import Stack, Duration
from aws_cdk import aws_lambda as lambda_
from aws_cdk import aws_apigateway as apigw
from constructs import Construct


class ApiStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        handler = lambda_.Function(
            self, "ApiHandler",
            runtime=lambda_.Runtime.NODEJS_20_X,
            handler="index.handler",
            code=lambda_.Code.from_asset("lambda"),
            memory_size=512,
            timeout=Duration.seconds(10),
        )

        apigw.LambdaRestApi(self, "PublicApi", handler=handler, proxy=True)

Custom stack props and the app entry point

A props interface becomes keyword-only parameters on the stack, env becomes an Environment struct, and the Python app ends with app.synth().

AWS CDK (TypeScript)
import { App, Stack, StackProps } from "aws-cdk-lib";
import * as sns from "aws-cdk-lib/aws-sns";
import { Construct } from "constructs";

interface AlertsStackProps extends StackProps {
  topicName: string;
}

export class AlertsStack extends Stack {
  constructor(scope: Construct, id: string, props: AlertsStackProps) {
    super(scope, id, props);
    new sns.Topic(this, "Alerts", { topicName: props.topicName });
  }
}

const app = new App();
new AlertsStack(app, "AlertsStack", {
  topicName: "ops-alerts",
  env: { account: "123456789012", region: "eu-west-1" },
});
AWS CDK (Python)
from aws_cdk import App, Environment, Stack
from aws_cdk import aws_sns as sns
from constructs import Construct


class AlertsStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, *, topic_name: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        sns.Topic(self, "Alerts", topic_name=topic_name)


app = App()
AlertsStack(
    app, "AlertsStack",
    topic_name="ops-alerts",
    env=Environment(account="123456789012", region="eu-west-1"),
)
app.synth()

Tips for better results

  • Paste the whole stack file, imports included. The imports tell the converter which modules and aliases the Python version needs.
  • Check third-party constructs. Libraries built with jsii publish Python packages. Constructs written only for TypeScript have to be rewritten.
  • Convert one stack per paste. Keep shared constructs in their own module and convert them separately.
  • Confirm with cdk diff. After switching the app command in cdk.json, a diff against the deployed stack should show no resource changes.
  • Port the tests. TypeScript Jest assertions translate to pytest with aws_cdk.assertions.Template.

Common mistakes when moving CDK to Python

  • Renaming construct IDs to snake_case. "OrderQueue" must stay "OrderQueue". Changing it changes the logical ID, and CloudFormation replaces the queue.
  • Passing stack props as one argument. Python stacks receive env, description and other stack props as keyword arguments. If you see props=props passed to super().__init__(), change it to **kwargs.
  • Importing a module as lambda. from aws_cdk import aws_lambda as lambda is a syntax error. Use an alias such as lambda_.
  • Dropping app.synth(). The TypeScript entry file usually doesn't call it, but the Python project template ends app.py with app.synth(). Keep it there.
  • Installing CDK v1 packages. Per-service packages such as aws-cdk.aws-s3 are CDK v1. For v2 you only need aws-cdk-lib and constructs.

Frequently asked questions

How do I convert AWS CDK TypeScript code to Python?

Paste a TypeScript stack into the converter at the top of this page and press Convert to Python. It rewrites the imports, turns props objects into snake_case keyword arguments and keeps every construct ID. Then run the code from a Python CDK project and confirm with cdk diff that nothing will be replaced.

Will switching the CDK app to Python replace my deployed resources?

Not if the stack names and construct IDs stay exactly the same. CloudFormation logical IDs come from the construct tree, so an unchanged tree produces the same template. Run cdk diff before deploying to confirm. The guide to translate an AWS CDK TypeScript app to Python shows how to confirm the template stays the same.

Why does the Python code use <code>lambda_</code>?

lambda is a reserved word in Python, so the CDK module is imported under an alias, for example from aws_cdk import aws_lambda as lambda_. The classes are identical to the TypeScript ones.

Do all CDK construct libraries work in Python?

Libraries built with jsii, including aws-cdk-lib and many Construct Hub packages, publish Python bindings. A construct written only in TypeScript for your project needs converting too.

What do I change in cdk.json?

Point the app command at the Python entry point, typically python3 app.py, and run it from a virtual environment with aws-cdk-lib and constructs installed.

Can I convert a whole CDK project at once?

Convert it one file at a time. Each conversion accepts up to 60,000 characters, and stack files convert most reliably on their own. Convert shared constructs first, then each stack, then bin/app.ts into app.py.

Can it convert my Jest tests to pytest?

You can paste a test file to get a first draft. The assertions module has the same API in both languages, so Template.fromStack(stack) becomes Template.from_stack(stack). Jest matchers and setup still need adapting to pytest by hand.

Is my code stored?

No. Your code is sent to an AI model hosted on NVIDIA's API only to produce the conversion, and ChatWithCloud doesn't store or log it. Your latest draft is kept only in your browser. For the full picture, see whether it's safe to paste AWS code into an AI converter.

Is the converter free?

Yes. Without an account you can run 6 conversions a minute and 60 a day. A free account raises that to 12 a minute and 200 a day and lists your recent conversions on your dashboard. The guide to ChatWithCloud free converter limits shows how far they stretch for a real migration.

Related tools and next steps