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
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!
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.
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.
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.
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
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.
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
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