How to Connect Python to Firebase Database: Complete Guide

Firebase is Google's comprehensive app development platform that provides cloud-hosted NoSQL databases, real-time synchronization, and backend services. When combined with Python, Firebase enables developers to build serverless, real-time applications with minimal infrastructure management. This comprehensive guide covers everything you need to know about connecting Python to Firebase.

Why Use Firebase with Python?

Firebase with Python offers powerful capabilities:

  • Real-time database with automatic synchronization
  • Cloud Firestore for flexible, scalable NoSQL storage
  • Serverless architecture with no infrastructure management
  • Built-in authentication and security rules
  • Automatic scaling based on demand
  • Offline support and data persistence
  • Real-time listeners for live updates
  • Perfect for mobile and web app backends

Prerequisites

Before connecting Python to Firebase, ensure you have:

  • Python 3.6 or higher installed
  • Firebase project created in Firebase Console
  • Service account credentials (JSON file)
  • Basic understanding of NoSQL databases
  • Firebase Admin SDK installed

Installing Firebase Admin SDK

Install the official Firebase Admin SDK for Python:

bash

pip install firebase-admin

Setting Up Firebase Project

  1. Go to Firebase Console (console.firebase.google.com)
  2. Create a new project or select existing
  3. Navigate to Project Settings > Service Accounts
  4. Generate new private key (downloads JSON file)
  5. Save the JSON file securely

Basic Connection to Firebase

python

import firebase_admin
from firebase_admin import credentials, firestore

# Initialize Firebase with service account
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)

# Get Firestore client
db = firestore.client()

print("Connected to Firebase successfully!")

Connection with Error Handling

python

import firebase_admin
from firebase_admin import credentials, firestore
from firebase_admin.exceptions import FirebaseError

def initialize_firebase():
    try:
        # Check if already initialized
        if not firebase_admin._apps:
            cred = credentials.Certificate('/path/to/serviceAccountKey.json')
            firebase_admin.initialize_app(cred)
        
        db = firestore.client()
        print("Successfully connected to Firebase")
        return db
        
    except FileNotFoundError:
        print("Service account key file not found")
        return None
    except FirebaseError as e:
        print(f"Firebase error: {e}")
        return None
    except Exception as e:
        print(f"Error: {e}")
        return None

# Usage
db = initialize_firebase()

Using Environment Variables

python

import firebase_admin
from firebase_admin import credentials
import os

# Set environment variable
# export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccountKey.json"

# Initialize with default credentials
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred)

print("Initialized with application default credentials")

Working with Firestore

Creating Documents

python

import firebase_admin
from firebase_admin import credentials, firestore
from datetime import datetime

# Initialize Firebase
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Add document with auto-generated ID
employee_ref = db.collection('employees').document()
employee_ref.set({
    'first_name': 'John',
    'last_name': 'Doe',
    'email': 'john.doe@company.com',
    'department': 'Engineering',
    'salary': 75000,
    'hire_date': datetime.now(),
    'skills': ['Python', 'Firebase', 'Cloud'],
    'active': True
})

print(f"Employee created with ID: {employee_ref.id}")

# Add document with custom ID
db.collection('employees').document('EMP001').set({
    'first_name': 'Jane',
    'last_name': 'Smith',
    'email': 'jane@company.com',
    'department': 'Marketing',
    'salary': 68000
})

print("Employee created with custom ID: EMP001")

Adding Multiple Documents

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Add multiple documents
employees = [
    {'first_name': 'Bob', 'last_name': 'Johnson', 'department': 'Sales', 'salary': 72000},
    {'first_name': 'Alice', 'last_name': 'Williams', 'department': 'Engineering', 'salary': 80000},
    {'first_name': 'Charlie', 'last_name': 'Brown', 'department': 'HR', 'salary': 62000}
]

for emp in employees:
    db.collection('employees').add(emp)
    print(f"Added employee: {emp['first_name']} {emp['last_name']}")

print(f"Added {len(employees)} employees")

Reading Documents

Get Single Document

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Get document by ID
doc_ref = db.collection('employees').document('EMP001')
doc = doc_ref.get()

if doc.exists:
    employee = doc.to_dict()
    print(f"Employee: {employee['first_name']} {employee['last_name']}")
    print(f"Department: {employee['department']}")
    print(f"Salary: ${employee['salary']}")
else:
    print("Document not found")

Get All Documents in Collection

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Get all employees
employees_ref = db.collection('employees')
docs = employees_ref.stream()

print("All Employees:")
for doc in docs:
    employee = doc.to_dict()
    print(f"ID: {doc.id}, Name: {employee['first_name']} {employee['last_name']}")

Query with Filters

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Query employees in Engineering department
engineers_ref = db.collection('employees').where('department', '==', 'Engineering')
docs = engineers_ref.stream()

print("Engineering Employees:")
for doc in docs:
    employee = doc.to_dict()
    print(f"{employee['first_name']} {employee['last_name']} - ${employee['salary']}")

# Multiple filters
high_earners = db.collection('employees')\
    .where('department', '==', 'Engineering')\
    .where('salary', '>', 70000)\
    .stream()

print("\nHigh-earning Engineers:")
for doc in high_earners:
    employee = doc.to_dict()
    print(f"{employee['first_name']} {employee['last_name']} - ${employee['salary']}")

Query with Ordering and Limiting

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Get top 5 highest paid employees
top_earners = db.collection('employees')\
    .order_by('salary', direction=firestore.Query.DESCENDING)\
    .limit(5)\
    .stream()

print("Top 5 Earners:")
for idx, doc in enumerate(top_earners, 1):
    employee = doc.to_dict()
    print(f"{idx}. {employee['first_name']} {employee['last_name']} - ${employee['salary']}")

Updating Documents

Update Specific Fields

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Update specific fields
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
    'salary': 85000,
    'department': 'Senior Engineering'
})

print("Employee updated successfully")

# Update using field path
doc_ref.update({
    'skills': firestore.ArrayUnion(['Docker', 'Kubernetes'])
})

print("Skills added to employee")

Increment Numeric Fields

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Increment salary
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
    'salary': firestore.Increment(5000)
})

print("Salary incremented by $5000")

Update or Create (Upsert)

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Set with merge (updates if exists, creates if doesn't)
doc_ref = db.collection('employees').document('EMP002')
doc_ref.set({
    'first_name': 'Sarah',
    'last_name': 'Connor',
    'department': 'Security'
}, merge=True)

print("Document upserted successfully")

Deleting Documents

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Delete a document
doc_ref = db.collection('employees').document('EMP999')
doc_ref.delete()

print("Employee deleted")

# Delete a field from document
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
    'temp_field': firestore.DELETE_FIELD
})

print("Field deleted from document")

Batch Operations

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Create batch
batch = db.batch()

# Add multiple operations to batch
emp1_ref = db.collection('employees').document('EMP001')
batch.update(emp1_ref, {'salary': 90000})

emp2_ref = db.collection('employees').document('EMP002')
batch.set(emp2_ref, {'first_name': 'New', 'last_name': 'Employee', 'department': 'IT'})

emp3_ref = db.collection('employees').document('EMP003')
batch.delete(emp3_ref)

# Commit batch
batch.commit()

print("Batch operations completed")

Transactions

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Transaction for atomic operations
@firestore.transactional
def transfer_budget(transaction, from_dept_ref, to_dept_ref, amount):
    # Read documents
    from_dept = from_dept_ref.get(transaction=transaction).to_dict()
    to_dept = to_dept_ref.get(transaction=transaction).to_dict()
    
    # Check if sufficient budget
    if from_dept['budget'] < amount:
        raise ValueError("Insufficient budget")
    
    # Perform transfer
    transaction.update(from_dept_ref, {'budget': from_dept['budget'] - amount})
    transaction.update(to_dept_ref, {'budget': to_dept['budget'] + amount})

# Execute transaction
from_ref = db.collection('departments').document('Engineering')
to_ref = db.collection('departments').document('Marketing')

transaction = db.transaction()
try:
    transfer_budget(transaction, from_ref, to_ref, 10000)
    print("Budget transfer completed successfully")
except ValueError as e:
    print(f"Transaction failed: {e}")

Real-time Listeners

python

import firebase_admin
from firebase_admin import credentials, firestore
import time

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Create a callback function
def on_snapshot(doc_snapshot, changes, read_time):
    for doc in doc_snapshot:
        print(f"Received document snapshot: {doc.id}")
        employee = doc.to_dict()
        print(f"Name: {employee['first_name']} {employee['last_name']}")
    
    for change in changes:
        if change.type.name == 'ADDED':
            print(f"New employee: {change.document.id}")
        elif change.type.name == 'MODIFIED':
            print(f"Modified employee: {change.document.id}")
        elif change.type.name == 'REMOVED':
            print(f"Removed employee: {change.document.id}")

# Watch a collection
employees_ref = db.collection('employees')
doc_watch = employees_ref.on_snapshot(on_snapshot)

print("Listening for changes... Press Ctrl+C to stop")

# Keep the script running
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("\nStopping listener")
    doc_watch.unsubscribe()

Working with Subcollections

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Create document with subcollection
employee_ref = db.collection('employees').document('EMP001')

# Add performance reviews as subcollection
reviews_ref = employee_ref.collection('reviews')
reviews_ref.add({
    'year': 2024,
    'rating': 'Excellent',
    'comments': 'Outstanding performance',
    'reviewer': 'Manager Name'
})

print("Review added to subcollection")

# Query subcollection
reviews = employee_ref.collection('reviews')\
    .where('year', '==', 2024)\
    .stream()

print("\n2024 Reviews:")
for review in reviews:
    data = review.to_dict()
    print(f"Rating: {data['rating']}, Comments: {data['comments']}")

Working with Array Fields

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

doc_ref = db.collection('employees').document('EMP001')

# Add elements to array
doc_ref.update({
    'skills': firestore.ArrayUnion(['GraphQL', 'TypeScript'])
})

print("Skills added to array")

# Remove elements from array
doc_ref.update({
    'skills': firestore.ArrayRemove(['GraphQL'])
})

print("Skill removed from array")

# Query documents containing array element
docs = db.collection('employees')\
    .where('skills', 'array_contains', 'Python')\
    .stream()

print("\nEmployees with Python skill:")
for doc in docs:
    employee = doc.to_dict()
    print(f"{employee['first_name']} {employee['last_name']}")

Using Firebase Realtime Database

python

import firebase_admin
from firebase_admin import credentials, db

# Initialize with Realtime Database URL
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred, {
    'databaseURL': 'https://your-project.firebaseio.com'
})

# Get reference to database
ref = db.reference('/')

# Write data
employees_ref = ref.child('employees')
employees_ref.set({
    'EMP001': {
        'first_name': 'John',
        'last_name': 'Doe',
        'department': 'Engineering',
        'salary': 75000
    },
    'EMP002': {
        'first_name': 'Jane',
        'last_name': 'Smith',
        'department': 'Marketing',
        'salary': 68000
    }
})

print("Data written to Realtime Database")

# Read data
employee = employees_ref.child('EMP001').get()
print(f"\nEmployee: {employee['first_name']} {employee['last_name']}")

# Update data
employees_ref.child('EMP001').update({
    'salary': 80000
})

print("Employee salary updated")

# Delete data
employees_ref.child('EMP002').delete()
print("Employee deleted")

Working with Cloud Storage

python

import firebase_admin
from firebase_admin import credentials, storage

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred, {
    'storageBucket': 'your-project.appspot.com'
})

# Get bucket
bucket = storage.bucket()

# Upload file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.upload_from_filename('/path/to/local/photo.jpg')

print("File uploaded successfully")

# Make file publicly accessible
blob.make_public()
print(f"Public URL: {blob.public_url}")

# Download file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.download_to_filename('/path/to/download/photo.jpg')

print("File downloaded successfully")

# Delete file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.delete()

print("File deleted")

Authentication

python

import firebase_admin
from firebase_admin import credentials, auth

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)

# Create user
user = auth.create_user(
    email='user@example.com',
    password='secretPassword',
    display_name='John Doe'
)

print(f"User created: {user.uid}")

# Get user by email
user = auth.get_user_by_email('user@example.com')
print(f"User: {user.display_name}, Email: {user.email}")

# Update user
auth.update_user(
    user.uid,
    display_name='John Smith',
    email_verified=True
)

print("User updated")

# Delete user
auth.delete_user(user.uid)
print("User deleted")

# Create custom token
custom_token = auth.create_custom_token(user.uid)
print(f"Custom token created: {custom_token.decode()}")

# Verify ID token
try:
    decoded_token = auth.verify_id_token(id_token)
    uid = decoded_token['uid']
    print(f"Token verified for user: {uid}")
except Exception as e:
    print(f"Token verification failed: {e}")

Complete Application Example

python

import firebase_admin
from firebase_admin import credentials, firestore
from datetime import datetime

class EmployeeManager:
    def __init__(self, service_account_path):
        if not firebase_admin._apps:
            cred = credentials.Certificate(service_account_path)
            firebase_admin.initialize_app(cred)
        
        self.db = firestore.client()
        self.collection = 'employees'
    
    def create_employee(self, first_name, last_name, email, department, salary):
        """Create a new employee"""
        doc_ref = self.db.collection(self.collection).document()
        doc_ref.set({
            'first_name': first_name,
            'last_name': last_name,
            'email': email,
            'department': department,
            'salary': salary,
            'hire_date': datetime.now(),
            'active': True
        })
        return doc_ref.id
    
    def get_employee(self, employee_id):
        """Get employee by ID"""
        doc = self.db.collection(self.collection).document(employee_id).get()
        if doc.exists:
            return {'id': doc.id, **doc.to_dict()}
        return None
    
    def get_all_employees(self):
        """Get all employees"""
        docs = self.db.collection(self.collection).stream()
        employees = []
        for doc in docs:
            employees.append({'id': doc.id, **doc.to_dict()})
        return employees
    
    def get_employees_by_department(self, department):
        """Get employees by department"""
        docs = self.db.collection(self.collection)\
            .where('department', '==', department)\
            .stream()
        
        employees = []
        for doc in docs:
            employees.append({'id': doc.id, **doc.to_dict()})
        return employees
    
    def update_salary(self, employee_id, new_salary):
        """Update employee salary"""
        doc_ref = self.db.collection(self.collection).document(employee_id)
        doc_ref.update({'salary': new_salary})
        return True
    
    def add_skill(self, employee_id, skill):
        """Add skill to employee"""
        doc_ref = self.db.collection(self.collection).document(employee_id)
        doc_ref.update({
            'skills': firestore.ArrayUnion([skill])
        })
        return True
    
    def delete_employee(self, employee_id):
        """Soft delete employee"""
        doc_ref = self.db.collection(self.collection).document(employee_id)
        doc_ref.update({'active': False})
        return True
    
    def search_employees(self, search_term):
        """Search employees by name"""
        # Note: Firestore doesn't support full-text search natively
        # This is a simple implementation
        all_employees = self.get_all_employees()
        results = []
        
        for emp in all_employees:
            full_name = f"{emp['first_name']} {emp['last_name']}".lower()
            if search_term.lower() in full_name:
                results.append(emp)
        
        return results
    
    def get_department_stats(self):
        """Get statistics by department"""
        docs = self.db.collection(self.collection).stream()
        
        stats = {}
        for doc in docs:
            employee = doc.to_dict()
            dept = employee.get('department', 'Unknown')
            
            if dept not in stats:
                stats[dept] = {
                    'count': 0,
                    'total_salary': 0,
                    'salaries': []
                }
            
            stats[dept]['count'] += 1
            stats[dept]['total_salary'] += employee.get('salary', 0)
            stats[dept]['salaries'].append(employee.get('salary', 0))
        
        # Calculate averages and ranges
        for dept in stats:
            salaries = stats[dept]['salaries']
            stats[dept]['avg_salary'] = stats[dept]['total_salary'] / stats[dept]['count']
            stats[dept]['min_salary'] = min(salaries)
            stats[dept]['max_salary'] = max(salaries)
            del stats[dept]['salaries']
            del stats[dept]['total_salary']
        
        return stats
    
    def add_performance_review(self, employee_id, year, rating, comments):
        """Add performance review as subcollection"""
        doc_ref = self.db.collection(self.collection).document(employee_id)
        reviews_ref = doc_ref.collection('reviews')
        reviews_ref.add({
            'year': year,
            'rating': rating,
            'comments': comments,
            'created_at': datetime.now()
        })
        return True
    
    def get_employee_reviews(self, employee_id):
        """Get all reviews for an employee"""
        doc_ref = self.db.collection(self.collection).document(employee_id)
        reviews = doc_ref.collection('reviews').stream()
        
        review_list = []
        for review in reviews:
            review_list.append({'id': review.id, **review.to_dict()})
        
        return review_list

# Usage
manager = EmployeeManager('/path/to/serviceAccountKey.json')

# Create employee
emp_id = manager.create_employee(
    'Sarah', 'Connor', 'sarah@company.com', 'Security', 78000
)
print(f"Created employee with ID: {emp_id}")

# Get employee
employee = manager.get_employee(emp_id)
print(f"Employee: {employee['first_name']} {employee['last_name']}")

# Get all employees
all_employees = manager.get_all_employees()
print(f"\nTotal employees: {len(all_employees)}")

# Get by department
engineers = manager.get_employees_by_department('Engineering')
print(f"Engineers: {len(engineers)}")

# Update salary
manager.update_salary(emp_id, 82000)
print("Salary updated")

# Add skill
manager.add_skill(emp_id, 'Cloud Security')
print("Skill added")

# Get department stats
stats = manager.get_department_stats()
print("\nDepartment Statistics:")
for dept, data in stats.items():
    print(f"{dept}:")
    print(f"  Employees: {data['count']}")
    print(f"  Avg Salary: ${data['avg_salary']:.2f}")
    print(f"  Range: ${data['min_salary']} - ${data['max_salary']}")

# Add performance review
manager.add_performance_review(emp_id, 2024, 'Excellent', 'Outstanding performance')
print("\nPerformance review added")

# Get reviews
reviews = manager.get_employee_reviews(emp_id)
print(f"Total reviews: {len(reviews)}")

# Search employees
results = manager.search_employees('Sarah')
print(f"\nSearch results: {len(results)} found")

Pagination

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Initial query
page_size = 10
employees_ref = db.collection('employees').limit(page_size)
docs = employees_ref.stream()

employees_list = list(docs)
print(f"Page 1: {len(employees_list)} employees")

# Get next page
if employees_list:
    last_doc = employees_list[-1]
    
    next_query = db.collection('employees')\
        .start_after(last_doc)\
        .limit(page_size)
    
    next_docs = next_query.stream()
    next_page = list(next_docs)
    
    print(f"Page 2: {len(next_page)} employees")

Security Rules Testing

python

import firebase_admin
from firebase_admin import credentials, firestore

cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# Test security rules (requires appropriate permissions)
try:
    # Attempt to access protected collection
    docs = db.collection('protected_data').stream()
    for doc in docs:
        print(f"Document: {doc.id}")
except Exception as e:
    print(f"Access denied: {e}")

Best Practices

Follow these best practices when using Firebase with Python:

  1. Secure service account keys - never commit to version control
  2. Use environment variables for credentials
  3. Implement proper error handling for all operations
  4. Use batch operations for multiple writes
  5. Leverage subcollections for hierarchical data
  6. Create indexes for complex queries
  7. Use transactions for atomic operations
  8. Monitor usage in Firebase Console
  9. Implement pagination for large datasets
  10. Use real-time listeners carefully to avoid costs
  11. Structure data to minimize reads
  12. Use security rules to protect data
  13. Cache frequently accessed data on client side
  14. Avoid deep nesting in documents
  15. Use appropriate data types for fields

Conclusion

Connecting Python to Firebase provides a powerful foundation for building serverless, real-time applications with minimal infrastructure management. Firebase's comprehensive suite of tools including Firestore, Realtime Database, Authentication, and Cloud Storage, combined with Python's versatility, enables rapid development of scalable applications. By following the examples and best practices in this guide, you'll be able to build robust applications that leverage Firebase's real-time capabilities, automatic scaling, and seamless integration with other Google Cloud services. Whether you're building mobile backends, web applications, or IoT platforms, mastering Python-Firebase connectivity is essential for modern serverless application development.

Subscribe to Transition from Excel to Python | Mito

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe