Save over 30% when you subscribe to an annual subscription plan!

Build a Currency Converter in 10 Minutes

Welcome to the API Ninjas currency converter tutorial! In this quick tutorial you'll learn how to build a beautiful, professional currency converter web application using Python Flask. This app will allow users to convert between different currencies using real-time exchange rates. We'll cover:

  • Setting up a Flask application

  • Making API calls to convert currencies

  • Handling user input with HTML forms

  • Creating a professional, modern UI

  • Advanced styling with modern CSS

Prerequisites:

  • Internet connection

  • Valid API Ninjas API key (get a free one here)

  • Python3 installed

  • Basic knowledge of Python (helpful but not required)

You can also download the finished code from our Github repository: https://github.com/API-Ninjas/API-Ninjas-currency-converter

Setup


First, let's install the required Python packages. Open a terminal window:

  • On Linux, press Ctrl + Alt + T.

  • On Mac OS, press Command + Space to open spotlight search, then type terminal.

  • On Windows, press Super + R, type cmd, and press Enter.

Install Flask using pip:

pip install flask

Install the requests package for making HTTP API calls:

pip install requests

Verify the installation by opening a Python shell and importing both packages:

python3
>>> import flask
>>> import requests
>>>

If there are no errors, you're ready to begin!

Building the Basic App


Let's start by creating a simple Flask application. Create a new file called app.py with the following code:

from flask import Flask, render_template, request
import requests

# Initialize Flask app.
app = Flask(__name__)

# Define the API URL for currency conversion.
CURRENCY_API_URL = 'https://api.api-ninjas.com/v1/convertcurrency'

# Your API key - replace with your actual key.
API_KEY = 'YOUR_API_KEY'

# Define routing.
@app.route('/')
def index():
    return render_template('index.html')

# Run the Flask app.
if __name__ == '__main__':
    app.run(debug=True)

This sets up a basic Flask application with a single route. Next, we'll add the API functionality and user interface.

Adding Currency Conversion


Now let's add a route that handles the currency conversion. Update your app.py file to include a new route for handling conversions:

from flask import Flask, render_template, request
import requests

# Initialize Flask app.
app = Flask(__name__)

# Define the API URL for currency conversion.
CURRENCY_API_URL = 'https://api.api-ninjas.com/v1/convertcurrency'

# Your API key - replace with your actual key.
API_KEY = 'YOUR_API_KEY'

# Define routing.
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/convert', methods=['POST'])
def convert():
    # Get form data.
    amount = request.form.get('amount')
    from_currency = request.form.get('from_currency')
    to_currency = request.form.get('to_currency')
    
    # Make API call.
    params = {
        'have': from_currency,
        'want': to_currency,
        'amount': amount
    }
    
    response = requests.get(
        CURRENCY_API_URL,
        params=params,
        headers={'X-Api-Key': API_KEY}
    )
    
    if response.status_code == 200:
        data = response.json()
        result = data.get('new_amount')
        # Calculate exchange rate
        rate = result / float(amount)
        return render_template('index.html', 
                             amount=amount,
                             from_currency=from_currency,
                             to_currency=to_currency,
                             result=result,
                             rate=rate)
    else:
        error = 'Error converting currency. Please try again.'
        return render_template('index.html', error=error)

# Run the Flask app.
if __name__ == '__main__':
    app.run(debug=True)

This route accepts POST requests from a form, makes an API call to convert the currency, and returns the result to the template.

Creating the User Interface


Now let's create the HTML interface with a beautiful, professional design. From the directory containing app.py, create a new folder called templates. Inside this folder, create a file named index.html:

<!--templates/index.html-->

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Currency Converter - API Ninjas</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <div class="converter-wrapper">
        <div class="logo">
            <h1>💱 Currency Converter</h1>
        </div>

        <div class="converter-card">
            <div class="form-header">
                <h2>Convert currency</h2>
                <p>Get accurate, real-time exchange rates for international currencies</p>
            </div>
            
            {% if error %}
            <div class="alert alert-error">{{ error }}</div>
            {% endif %}
            
            <form method="POST" action="/convert">
                <div class="form-group">
                    <label for="amount">Amount</label>
                    <input type="number" 
                           id="amount" 
                           name="amount" 
                           step="0.01" 
                           value="{{ amount or '100.00' }}" 
                           required>
                </div>
                
                <div class="form-row">
                    <div class="form-group">
                        <label for="from_currency">From</label>
                        <select id="from_currency" name="from_currency" required>
                            <option value="USD" {% if from_currency == 'USD' %}selected{% endif %}>USD - US Dollar</option>
                            <option value="EUR" {% if from_currency == 'EUR' %}selected{% endif %}>EUR - Euro</option>
                            <option value="GBP" {% if from_currency == 'GBP' %}selected{% endif %}>GBP - British Pound</option>
                            <option value="JPY" {% if from_currency == 'JPY' %}selected{% endif %}>JPY - Japanese Yen</option>
                            <option value="AUD" {% if from_currency == 'AUD' %}selected{% endif %}>AUD - Australian Dollar</option>
                            <option value="CAD" {% if from_currency == 'CAD' %}selected{% endif %}>CAD - Canadian Dollar</option>
                            <option value="CHF" {% if from_currency == 'CHF' %}selected{% endif %}>CHF - Swiss Franc</option>
                            <option value="CNY" {% if from_currency == 'CNY' %}selected{% endif %}>CNY - Chinese Yuan</option>
                            <option value="INR" {% if from_currency == 'INR' %}selected{% endif %}>INR - Indian Rupee</option>
                        </select>
                    </div>
                    
                    <div class="form-group">
                        <label for="to_currency">To</label>
                        <select id="to_currency" name="to_currency" required>
                            <option value="USD" {% if to_currency == 'USD' %}selected{% endif %}>USD - US Dollar</option>
                            <option value="EUR" {% if to_currency == 'EUR' %}selected{% endif %}>EUR - Euro</option>
                            <option value="GBP" {% if to_currency == 'GBP' %}selected{% endif %}>GBP - British Pound</option>
                            <option value="JPY" {% if to_currency == 'JPY' %}selected{% endif %}>JPY - Japanese Yen</option>
                            <option value="AUD" {% if to_currency == 'AUD' %}selected{% endif %}>AUD - Australian Dollar</option>
                            <option value="CAD" {% if to_currency == 'CAD' %}selected{% endif %}>CAD - Canadian Dollar</option>
                            <option value="CHF" {% if to_currency == 'CHF' %}selected{% endif %}>CHF - Swiss Franc</option>
                            <option value="CNY" {% if to_currency == 'CNY' %}selected{% endif %}>CNY - Chinese Yuan</option>
                            <option value="INR" {% if to_currency == 'INR' %}selected{% endif %}>INR - Indian Rupee</option>
                        </select>
                    </div>
                </div>
                
                <button type="submit" class="btn-primary">Convert currency</button>
            </form>
            
            {% if result %}
            <div class="result-box">
                <div class="result-label">Converted Amount</div>
                <div class="result-text">
                    {{ amount }} {{ from_currency }} = 
                    <span class="result-amount">{{ "%.2f"|format(result) }} {{ to_currency }}</span>
                </div>
                <div class="rate-info">
                    Exchange rate: 1 {{ from_currency }} = {{ "%.4f"|format(rate) }} {{ to_currency }}
                </div>
            </div>
            {% endif %}
        </div>

        <div class="footer">
            Powered by <a href="https://api-ninjas.com" target="_blank">API Ninjas</a>
        </div>
    </div>
</body>
</html>

This HTML template creates a professional form with inputs for the amount and currency selection. It uses the Inter font for clean typography and displays the conversion result in an elegant format.

Adding Professional Styles


Let's add CSS to make our converter look professional and modern. From your app.py directory, create a folder called static, then create a css folder inside it. Create a file named style.css with the following code:

/* static/css/style.css */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100%;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background: #f6f9fc;
    background-image: 
        radial-gradient(at 27% 37%, hsla(215, 98%, 61%, 0.03) 0px, transparent 50%),
        radial-gradient(at 97% 21%, hsla(125, 98%, 72%, 0.03) 0px, transparent 50%),
        radial-gradient(at 52% 99%, hsla(354, 98%, 61%, 0.03) 0px, transparent 50%),
        radial-gradient(at 10% 29%, hsla(256, 96%, 67%, 0.03) 0px, transparent 50%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.converter-wrapper {
    max-width: 520px;
    width: 100%;
}

.logo {
    text-align: center;
    margin-bottom: 32px;
}

.logo h1 {
    font-size: 28px;
    font-weight: 600;
    color: #0a2540;
    letter-spacing: -0.02em;
}

.converter-card {
    background: white;
    border-radius: 12px;
    padding: 48px;
    box-shadow: 
        0 0 0 1px rgba(0, 0, 0, 0.02),
        0 2px 4px rgba(0, 0, 0, 0.02),
        0 8px 16px rgba(0, 0, 0, 0.04);
    transition: box-shadow 0.3s ease;
}

.converter-card:hover {
    box-shadow: 
        0 0 0 1px rgba(0, 0, 0, 0.02),
        0 4px 8px rgba(0, 0, 0, 0.04),
        0 12px 24px rgba(0, 0, 0, 0.06);
}

.form-header {
    margin-bottom: 32px;
}

.form-header h2 {
    font-size: 20px;
    font-weight: 600;
    color: #0a2540;
    margin-bottom: 8px;
}

.form-header p {
    font-size: 15px;
    color: #425466;
    line-height: 1.5;
}

.form-group {
    margin-bottom: 24px;
}

label {
    display: block;
    font-size: 14px;
    font-weight: 500;
    color: #0a2540;
    margin-bottom: 8px;
}

input[type="number"],
select {
    width: 100%;
    padding: 12px 16px;
    font-size: 15px;
    font-family: 'Inter', sans-serif;
    color: #0a2540;
    background: white;
    border: 1px solid #e3e8ef;
    border-radius: 8px;
    transition: all 0.15s ease;
}

input[type="number"]:focus,
select:focus {
    outline: none;
    border-color: #635bff;
    box-shadow: 0 0 0 3px rgba(99, 91, 255, 0.1);
}

input[type="number"]:hover,
select:hover {
    border-color: #c1c7d0;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 24px;
}

.btn-primary {
    width: 100%;
    padding: 14px 24px;
    font-size: 15px;
    font-weight: 600;
    font-family: 'Inter', sans-serif;
    color: white;
    background: #635bff;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.15s ease;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.btn-primary:hover {
    background: #5348e6;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.16);
    transform: translateY(-1px);
}

.result-box {
    margin-top: 32px;
    padding: 24px;
    background: linear-gradient(135deg, #f6f9fc 0%, #eef2f6 100%);
    border: 1px solid #e3e8ef;
    border-radius: 8px;
    animation: slideIn 0.3s ease;
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.result-label {
    font-size: 13px;
    font-weight: 500;
    color: #425466;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 8px;
}

.result-text {
    font-size: 15px;
    color: #0a2540;
    line-height: 1.6;
}

.result-amount {
    display: block;
    font-size: 32px;
    font-weight: 700;
    color: #635bff;
    margin-top: 8px;
    letter-spacing: -0.02em;
}

.rate-info {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #e3e8ef;
    font-size: 13px;
    color: #697386;
}

.footer {
    text-align: center;
    margin-top: 24px;
    font-size: 13px;
    color: #697386;
}

.footer a {
    color: #635bff;
    text-decoration: none;
}

.footer a:hover {
    text-decoration: underline;
}

.alert-error {
    padding: 12px 16px;
    background: #fff1f0;
    border: 1px solid #ffccc7;
    border-radius: 8px;
    color: #cf1322;
    font-size: 14px;
    margin-bottom: 24px;
}

@media (max-width: 640px) {
    .converter-card {
        padding: 32px 24px;
    }

    .form-row {
        grid-template-columns: 1fr;
    }

    .result-amount {
        font-size: 28px;
    }
}

This CSS creates a professional, modern design with:

  • Inter font family for clean typography

  • Professional color palette (#635bff for brand purple, #0a2540 for dark navy)

  • Subtle radial gradient background mesh

  • Multi-layered shadows that create depth

  • Smooth transitions and micro-interactions

  • Clean, minimal form inputs with elegant focus states

Your project directory structure should now look like this:

currency-converter/
├── app.py
├── templates/
│   └── index.html
└── static/
    └── css/
        └── style.css

Running Your App


Now you're ready to run your beautiful currency converter! Make sure you've replaced YOUR_API_KEY in app.py with your actual API Ninjas API key.

From your terminal, navigate to the directory containing app.py and run:

python3 app.py

Open your web browser and navigate to http://127.0.0.1:5000. You should see your professionally-designed currency converter app with a modern, clean interface!



Try converting different amounts between various currencies. The app will display the converted amount along with the current exchange rate, all in a beautiful, professional interface.

Design Features

Your currency converter now includes several premium design elements:

  • Professional Typography: Uses Inter font for a clean, modern look

  • Subtle Animations: Smooth transitions on hover and form interactions

  • Layered Shadows: Multi-level shadows create depth and elevation

  • Brand Colors: Professional purple (#635bff) and navy (#0a2540)

  • Responsive Design: Works perfectly on mobile, tablet, and desktop

  • Focus States: Clear visual feedback with purple glow on form inputs

Next Steps

Congratulations! You've built a professional currency converter with a modern design in just 10 minutes. Here are some ideas to extend your app:

  • Add a swap button to quickly reverse the conversion

  • Include more currency options with flags

  • Display historical exchange rate charts

  • Add currency symbols (€, £, Â¥) next to amounts

  • Implement auto-conversion as the user types

  • Save recent conversions to local storage

  • Add dark mode support