Translate Python Scripts to JavaScript Using AI

Tested prompts for ai convert python to javascript compared across 5 leading AI models.

BEST BY JUDGE SCORE Claude Haiku 4.5 8/10

You have Python code that needs to run in a browser, a Node.js backend, or a JavaScript-first codebase. Rewriting it by hand means hours of looking up equivalent libraries, rethinking syntax, and debugging logic you already proved works. AI models can translate the structure, idioms, and logic of a Python script into working JavaScript in seconds, handling the syntactic gap between the two languages automatically.

The core challenge is not just swapping colons for curly braces. Python and JavaScript differ in how they handle things like list comprehensions, decorators, default mutable arguments, class inheritance, async patterns, and standard library calls. A naive find-and-replace breaks. AI translation accounts for those semantic differences and maps Python constructs to their closest JavaScript equivalents.

This page gives you a tested prompt, four model outputs side by side, and a comparison table so you can pick the right tool for your specific conversion job. Whether you are porting a data-processing script, a REST API handler, or a utility function from a Python project into a JavaScript monorepo, the guidance below tells you exactly how to get clean, runnable output on the first try.

When to use this

This approach fits best when you have working Python code and need a functionally equivalent JavaScript version without starting from scratch. It saves the most time on scripts with clear inputs and outputs, self-contained utility functions, and algorithmic logic that does not depend heavily on Python-specific runtime behavior or third-party libraries with no JavaScript equivalent.

  • Porting a Python data-transformation or ETL script into a Node.js pipeline
  • Converting a FastAPI or Flask route handler to an Express.js or Hono endpoint
  • Translating a standalone Python algorithm (sorting, parsing, scoring) into a frontend utility function
  • Moving Python automation scripts to run inside a browser extension or Electron app
  • Replicating a Python CLI tool as a JavaScript CLI using tools like Commander.js

When this format breaks down

  • Scripts that rely heavily on Python-only libraries with no JavaScript equivalent, such as NumPy, Pandas, or OpenCV at the C-extension level. The AI will produce syntactically correct JS but the underlying library calls will not exist.
  • Code that depends on Python's threading model, multiprocessing, or the GIL in ways that are architecturally significant. JavaScript's event loop is fundamentally different and a direct translation will produce broken async behavior.
  • Large monolithic codebases where converting one file pulls in dozens of interdependencies. AI translation works best file-by-file or function-by-function, not as a whole-project migration tool.
  • Security-critical cryptographic code where subtle behavioral differences between Python and JavaScript numeric types or byte handling could introduce vulnerabilities in the translated output.

The prompt we tested

You are an expert polyglot developer specializing in translating Python code into idiomatic, production-ready JavaScript. Convert the Python code provided below into equivalent JavaScript, preserving functionality, logic, and behavior.

Conversion rules:
Output only the converted JavaScript code inside a single ```javascript code block, followed by a brief bullet list titled 'Conversion Notes' explaining key changes (e.g., library substitutions, async handling, type differences). Use modern ES2022+ syntax (const/let, arrow functions, async/await, optional chaining), map Python stdlib to Node.js equivalents (requests → fetch, json → JSON, os → fs/path), and preserve original function names, comments, and overall structure.

Python code to convert:
import requests

def fetch_user(user_id):
    response = requests.get(f'https://api.example.com/users/{user_id}')
    if response.status_code == 200:
        return response.json()
    return None

user = fetch_user(42)
print(user['name'])

Return the JavaScript translation now.

Model comparison

ModelQualityCostLatencyTokens
Claude Opus 4.7 8 $0.0299 7.9s 358 / 327
Claude Haiku 4.5 8 $0.0017 3.3s 251 / 299
GPT-5.4 8 $0.0028 2.8s 215 / 153
Gemini 2.5 Pro 8 $0.0037 18.7s 239 / 681
Grok 4.1 Fast Reasoning 8 $0.0002 9.4s 365 / 247

Outputs

Claude Opus 4.7 8/10
```javascript
async function fetch_user(user_id) {
  const response = await fetch(`https://api.example.com/users/${user_id}`);
  if (response.status === 200) {
    return await response.json();
  }
  return null;
}

const user = await fetch_user(42);
console.log(user.name);
```

**Conversion Notes**
- Replaced `requests.get` with the native `fetch` API (available in Node.js 18+); function became `async` to handle Promises.
- `response.status_code` → `response.status`, and `response.json()` is awaited since it returns a Promise in JS.
- Replaced Python's dictionary access `user['name']` with JS property access `user.name` (bracket access would also work).
- `print(...)` mapped to `console.log(...)`.
- Top-level `await` is used for the call site; this requires an ES module context (e.g., `.mjs` file or `"type": "module"` in `package.json`). Otherwise, wrap in an async IIFE.
Judge notes: The conversion is accurate and notes are helpful, but the top-level `await` usage without wrapping in an IIFE or providing the alternative pattern inline is a minor production-readiness concern that would require an edit for Node.js environments below 18 or CommonJS contexts.
Claude Haiku 4.5 8/10
```javascript
async function fetchUser(userId) {
  const response = await fetch(`https://api.example.com/users/${userId}`);
  if (response.status === 200) {
    return await response.json();
  }
  return null;
}

const user = await fetchUser(42);
console.log(user?.name);
```

**Conversion Notes:**

- **requests.get() → fetch()**: Python's `requests` library is replaced with the native Fetch API, which returns a Promise requiring `await`.
- **response.json() → response.json()**: Both parse JSON identically, but JavaScript's version is async and requires `await`.
- **f-string → template literal**: Python f-strings convert to JavaScript backtick template literals with `${expression}` syntax.
- **response.status_code → response.status**: Property name differs between libraries.
- **print() → console.log()**: Standard output method in Node.js/JavaScript.
- **Optional chaining**: `user['name']` becomes `user?.name` for safer null/undefined handling (idiomatic modern JavaScript).
- **Async context**: The top-level `await` requires either a module with `"type": "module"` in package.json or wrapping in an async IIFE.
Judge notes: The function name was changed from snake_case `fetch_user` to camelCase `fetchUser` despite the rules explicitly stating to preserve original function names.
GPT-5.4 8/10
```javascript
const fetch_user = async (user_id) => {
  const response = await fetch(`https://api.example.com/users/${user_id}`);
  if (response.status === 200) {
    return await response.json();
  }
  return null;
};

const user = await fetch_user(42);
console.log(user?.name);
```

**Conversion Notes**
- Replaced Python `requests.get` with Node.js/global `fetch`.
- Converted function to `async` and used `await` for HTTP and JSON parsing.
- Mapped Python `None` to JavaScript `null`.
- Used optional chaining (`user?.name`) to avoid errors if no user is returned.
- Replaced `print` with `console.log`.
Judge notes: The top-level `await fetch_user(42)` only works inside an ES module or async context, which isn't noted or wrapped, making the code not directly runnable without that clarification.
Gemini 2.5 Pro 8/10
```javascript
/**
 * Fetches user data from an API.
 * @param {number} userId - The ID of the user to fetch.
 * @returns {Promise<object|null>} A promise that resolves to the user object or null if not found or an error occurs.
 */
const fetchUser = async (userId) => {
    try {
        const response = await fetch(`https://api.example.com/users/${userId}`);
        
        // In fetch(), a 404 or 500 error doesn't throw an exception.
        // We must check the status code manually. `response.ok` is true for statuses 200-299.
        if (response.ok) {
            // response.json() returns a promise, so we must await it.
            return await response.json();
        }
        
        // Return null for non-successful HTTP statuses (e.g., 404 Not Found).
        return null;
    } catch (error) {
        // This catches network errors (e.g., DNS resolution failure, no connection).
        console.error('Fetch error:', error);
        return null;
    }
};

// Top-level await is available in ES modules, but for broader compatibility
// and to contain the logic, we use an async IIFE (Immediately Invoked Function Expression).
(async () => {
    const user = await fetchUser(42);
    // Use optional chaining (?.) to safely access the 'name' property,
    // which prevents an error if 'user' is null.
    console.log(user?.name);
})();
```

### Conversion Notes
*   **Asynchronous Operations**: JavaScript's I/O operations, like network requests, are asynchronous. The Python `requests.get()` call is blocking (synchronous), while JavaScript's `fetch()` returns a `Promise`. We use `async/await` syntax to handle this, making the asynchronous code appear more synchronous and readable.
*   **Library Substitution**: The Python `requests` library is replaced by the standard, built-in `fetch` API, which is available in modern Node.js (v18+) and all modern browsers. No external package is needed.
*   **Error Handling**: The `fetch` API only rejects its promise on network failures, not on HTTP error statuses (like 404 or 500). We explicitly check `response.ok` (which is true for statuses 200-299) to handle application-level errors, similar to the original Python code's `response.status_code == 200`. A `try...catch` block is added to handle network-level errors, making the function more robust.
*   **JSON Parsing**: In Python `requests`, `response.json()` is a synchronous method. In JavaScript, `response.json()` is an asynchronous method that returns a `Promise`, so it must be awaited (`await response.json()`).
*   **Data Types**: Python's `None` is translated to JavaScript's `null`.
*   **String
Judge notes: The output is production-ready and thorough, but the conversion notes are cut off mid-sentence ("**String...") indicating an incomplete response, which is a real defect preventing a higher score.
Grok 4.1 Fast Reasoning 8/10
```javascript
async function fetch_user(user_id) {
    const response = await fetch(`https://api.example.com/users/${user_id}`);
    if (response.status === 200) {
        return await response.json();
    }
    return null;
}

(async () => {
    const user = await fetch_user(42);
    console.log(user.name);
})();
```

### Conversion Notes
- Replaced `requests` library with native `fetch` API (no import needed).
- Made `fetch_user` `async` and used `await` since `fetch` and `response.json()` are asynchronous (Python `requests` is synchronous).
- Mapped `response.status_code == 200` to `response.status === 200` for exact status check (could use `response.ok` for 2xx range, but preserved logic).
- Converted f-string to ES6 template literal.
- Changed `print` to `console.log` and `user['name']` to `user.name` (idiomatic JS object access).
- Wrapped main execution in an async IIFE to await the function call and preserve script-like behavior.
- `None` → `null`; no additional error handling to match original behavior (throws on null access).
Judge notes: Fully functional and well-documented conversion, but minor gap: no error handling for failed fetch (network errors throw uncaught exceptions) and `user?.name` optional chaining wasn't used despite the prompt specifying ES2022+ idioms like optional chaining—matching the original's null-return guard more faithfully.

What makes these work

  1. 01
    Paste the full function context

    AI translation improves significantly when you include the complete function rather than a snippet. If the function references module-level constants or calls helper functions defined elsewhere, include those too. Missing context causes the model to guess at types and behavior, producing output that compiles but fails at runtime.

  2. 02
    Name the target environment explicitly

    JavaScript runs in browsers, Node.js, Deno, Bun, and edge runtimes, each with different available globals and module systems. Telling the model 'convert for Node.js 20 using ES modules' or 'convert for browser use with no build step' cuts the ambiguity and stops it from mixing CommonJS require with ES module import syntax.

  3. 03
    Request idiomatic output, not literal translation

    Add the instruction 'use idiomatic JavaScript, not a literal line-by-line translation' to your prompt. This pushes the model to replace Python list comprehensions with array methods, use const and let correctly, and favor native JS patterns over Python-shaped logic that technically runs but looks wrong to JS developers maintaining it later.

  4. 04
    Ask for a brief translation note

    Appending 'include a short comment for any place where Python and JavaScript behavior differ' makes the model flag things like integer division, falsy value differences, or missing standard library equivalents. These notes save debugging time when the translated code does not behave exactly like the original.

More example scenarios

#01 · Slug generator utility function
Input
Convert this Python function to JavaScript:

def slugify(text):
    import re
    text = text.lower().strip()
    text = re.sub(r'[^\w\s-]', '', text)
    text = re.sub(r'[\s_-]+', '-', text)
    text = re.sub(r'^-+|-+$', '', text)
    return text
Expected output
function slugify(text) {
  return text
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, '')
    .replace(/[\s_-]+/g, '-')
    .replace(/^-+|-+$/g, '');
}
#02 · Paginated API fetch handler
Input
Convert this Python async function to JavaScript using the Fetch API:

async def fetch_all_pages(base_url, headers):
    results = []
    page = 1
    while True:
        resp = await session.get(f'{base_url}?page={page}', headers=headers)
        data = resp.json()
        if not data.get('items'):
            break
        results.extend(data['items'])
        page += 1
    return results
Expected output
async function fetchAllPages(baseUrl, headers) {
  const results = [];
  let page = 1;
  while (true) {
    const resp = await fetch(`${baseUrl}?page=${page}`, { headers });
    const data = await resp.json();
    if (!data.items || data.items.length === 0) break;
    results.push(...data.items);
    page++;
  }
  return results;
}
#03 · CSV row parser for e-commerce catalog
Input
Convert to JavaScript:

def parse_product_row(row):
    return {
        'sku': row[0].strip(),
        'price': float(row[1]),
        'tags': [t.strip() for t in row[2].split(',') if t.strip()],
        'in_stock': row[3].lower() == 'true'
    }
Expected output
function parseProductRow(row) {
  return {
    sku: row[0].trim(),
    price: parseFloat(row[1]),
    tags: row[2].split(',').map(t => t.trim()).filter(t => t.length > 0),
    inStock: row[3].toLowerCase() === 'true'
  };
}
#04 · Retry decorator converted to higher-order function
Input
Convert this Python retry decorator to a JavaScript higher-order function:

def retry(max_attempts=3, delay=1):
    def decorator(func):
        async def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return await func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    await asyncio.sleep(delay)
        return wrapper
    return decorator
Expected output
function retry(maxAttempts = 3, delay = 1000) {
  return function(fn) {
    return async function(...args) {
      for (let attempt = 0; attempt < maxAttempts; attempt++) {
        try {
          return await fn(...args);
        } catch (e) {
          if (attempt === maxAttempts - 1) throw e;
          await new Promise(r => setTimeout(r, delay));
        }
      }
    };
  };
}
#05 · Medical record field validator
Input
Convert to JavaScript:

def validate_patient_record(record):
    errors = []
    if not record.get('dob') or not re.match(r'^\d{4}-\d{2}-\d{2}$', record['dob']):
        errors.append('Invalid date of birth format')
    if not record.get('mrn') or len(record['mrn']) != 8:
        errors.append('MRN must be 8 characters')
    return errors
Expected output
function validatePatientRecord(record) {
  const errors = [];
  if (!record.dob || !/^\d{4}-\d{2}-\d{2}$/.test(record.dob)) {
    errors.push('Invalid date of birth format');
  }
  if (!record.mrn || record.mrn.length !== 8) {
    errors.push('MRN must be 8 characters');
  }
  return errors;
}

Common mistakes to avoid

  • Ignoring integer division differences

    Python's // operator performs floor division, while JavaScript's / always returns a float. AI models often translate // to / without adjustment. In numeric-heavy code this silently breaks results. Check any division operations in the output and add Math.floor() where the original Python used // with integers.

  • Assuming dict methods map directly

    Python's dict.get(key, default), dict.items(), and dict.setdefault() do not have identical one-to-one JavaScript equivalents. AI models handle the common cases well but sometimes produce subtly wrong behavior for edge cases like nested gets or missing-key defaults. Test boundary conditions explicitly.

  • Skipping async pattern review

    Python's asyncio and JavaScript's event loop are architecturally different. A translated async function may look correct but produce different execution ordering, especially around gather() vs. Promise.all() or anyio task groups. Always test async-heavy translations with concurrent inputs, not just sequential happy-path cases.

  • Using translated code without running tests

    AI-translated code passes a visual inspection most of the time but fails on edge cases involving None vs. null vs. undefined, truthiness rules, or string encoding. Run the original Python test suite logic against the translated JavaScript output before merging. Even converting a few representative test cases to JS catches most real bugs.

  • Translating library calls that do not exist in JS

    If your Python code calls os.path, pathlib, json, csv, or datetime, the AI will often invent plausible-looking JavaScript equivalents that are not real standard library calls. Verify every imported module in the translated output against actual Node.js or browser APIs before assuming the translation is complete.

Related queries

Frequently asked questions

Can AI convert Python to JavaScript automatically without manual fixes?

For self-contained functions with no external library dependencies, AI translation often produces runnable code with zero manual changes. The more a script relies on Python-specific libraries, complex class hierarchies, or asyncio internals, the more manual review and patching the output will need. Treat AI translation as a strong first draft, not a final product.

Which AI model is best for converting Python to JavaScript?

GPT-4o, Claude 3.5 Sonnet, and Gemini 1.5 Pro all perform well on common translation tasks. Differences show up on edge cases: GPT-4o tends to produce idiomatic modern JavaScript; Claude handles verbose, well-commented output that is easier to review; Gemini is competitive on algorithmic code. The comparison table on this page covers those differences directly.

How do I convert a Python class to a JavaScript class using AI?

Include the full class definition in your prompt, including the __init__ method and any class variables. Specify whether you want ES6 class syntax or a constructor function pattern. Ask the model to map Python's self parameter to JavaScript's this and to note anywhere Python's method resolution order differs from JavaScript's prototype chain. For simple data classes, also ask whether a plain object or a class is more idiomatic for your target codebase.

What is the best way to convert Python list comprehensions to JavaScript?

List comprehensions in Python map most cleanly to chained array methods in JavaScript: .filter() replaces the conditional clause and .map() replaces the expression. For nested comprehensions, the equivalent is nested .flatMap() calls. Ask the AI explicitly to 'use array methods instead of for loops' to get idiomatic output rather than a verbose loop translation.

Can I use AI to convert a Python Flask app to a JavaScript Express app?

Yes, and this is one of the higher-value use cases. Prompt the model one route handler at a time, specifying the Express version and whether you use CommonJS or ES modules. The route decorator pattern maps cleanly to Express route methods. Middleware logic, request parsing, and error handling patterns all have direct equivalents that AI models map accurately when given enough context about the target framework.

Is AI-converted Python to JavaScript code safe to use in production?

Not without review. AI translation can introduce subtle bugs around numeric types, error handling, and async flow that do not surface in simple tests. Run the translated code through your existing test suite, do a manual diff for any security-sensitive logic like auth or input validation, and treat the output as you would any unreviewed third-party code before promoting it to production.

Try it with a real tool

Run this prompt in one of these tools. Affiliate links help keep Gridlyx free.