A high-performance REST API providing comprehensive German street data with advanced search capabilities. Search through 500,000+ German streets, cities, postal codes, and administrative divisions.
- Overview
- Features
- Quick Start
- API Documentation
- Installation
- Configuration
- Usage Examples
- Data Source
- Troubleshooting
- License
- Acknowledgments
The German Streets API provides a powerful, searchable database of German addresses including street names, cities, postal codes, regional keys, and borough information. Built with performance in mind, it offers flexible search capabilities with multiple operators and field combinations.
Perfect for:
- Address validation and autocomplete systems
- Geographic applications requiring German address data
- Location-based services and mapping applications
- Data analysis and research projects
- Integration with e-commerce checkout systems
The API automatically synchronizes with the latest data from the OpenPLZ API project, ensuring up-to-date information.
For detailed API reference, programming examples, and interactive documentation, visit the comprehensive guide above.
✅ 500,000+ German addresses with complete geographic data
✅ Advanced search operators (contains, equals, starts_with, ends_with, not_contains, not_equals)
✅ Multi-field filtering with AND/OR logic support
✅ Flexible field selection - request only the data you need
✅ Pagination support for handling large result sets
✅ Rate limiting and request logging for production use
✅ Health monitoring and status endpoints
✅ Docker-ready with complete containerization
✅ Automatic data updates twice daily from official sources
✅ RESTful design with JSON responses
✅ CORS support for browser-based applications
Get the API running locally in under 2 minutes:
# Clone the repository
git clone https://github.com/yourusername/german-streets-api.git
cd german-streets-api
# Start with Docker Compose
docker compose up -d
# Wait for initial data load (this may take a few minutes on first run)
docker compose logs -f php-fpm
# Test the API
curl "http://localhost:8080/api/search.php?field=street_name&operator=contains&value=Haupt&limit=5"Example Response:
{
"success": true,
"data": {
"results": [
{
"street_name": "Hauptstraße",
"city_name": "Berlin",
"zip_code": "10115",
"regional_key": "11000000",
"borough_name": "Mitte"
}
],
"count": 1,
"total": 1543,
"limit": 5,
"offset": 0,
"has_more": true
}
}GET /api/search.php
The primary endpoint for searching German address data.
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
field |
string | No | Field to search in | street_name |
operator |
string | No | Search operator | contains |
value |
string | Yes | Search value | - |
limit |
integer | No | Maximum results (1-1777) | 100 |
offset |
integer | No | Results offset for pagination | 0 |
fields |
string | No | Comma-separated list of fields to return | All fields |
| Parameter | Type | Required | Description |
|---|---|---|---|
filters |
JSON string | Yes | Array of filter objects |
logic |
string | No | Logic operator for combining filters (AND or OR) |
limit |
integer | No | Maximum results (1-1777) |
offset |
integer | No | Results offset for pagination |
fields |
string | No | Comma-separated list of fields to return |
Filter Object Structure:
{
"field": "street_name",
"operator": "contains",
"value": "Haupt"
}All responses follow this structure:
{
"success": true|false,
"data": {
"results": [...],
"count": 25,
"total": 1543,
"limit": 25,
"offset": 0,
"has_more": true
},
"error": "Error message (only if success: false)"
}| Operator | Description | Example |
|---|---|---|
contains |
Field contains the value (case-insensitive) | value=haupt matches "Hauptstraße" |
contains_not |
Field does not contain the value | value=haupt excludes streets with "haupt" |
equals |
Exact match (case-sensitive) | value=Berlin matches only "Berlin" |
equals_not |
Does not equal (case-sensitive) | value=Berlin excludes "Berlin" |
starts_with |
Field starts with the value | value=Haupt matches "Hauptstraße" |
ends_with |
Field ends with the value | value=straße matches "Hauptstraße" |
| Field | Type | Description | Example |
|---|---|---|---|
street_name |
string | Street name | "Hauptstraße" |
city_name |
string | City/locality name | "Berlin" |
zip_code |
string | Postal code | "10115" |
regional_key |
string | Official regional key | "11000000" |
borough_name |
string | Borough/district name | "Mitte" |
Requirements:
- Docker 20.10+
- Docker Compose 2.0+
Quick Setup:
git clone https://github.com/madLinux7/german-streets-api.git
cd german-streets-api
docker compose up -dAccessing Services:
- API: http://localhost:8080/api/search
- Health Check: http://localhost:8080/health
- Database: localhost:5432 (credentials in docker-compose.yml)
Initial and manual Data Fetch:
Trigger immediate data fetch - run this after the container startup to import all streets and city data!
docker exec gsa_php php /var/www/html/fetch_streets.phpFor production deployment consider using Coolify:
- Self-Hosting & No Vendor Lock-in: Full control over applications and data on your own servers.
- Cost-Effective: A free, open-source solution—pay only for your server.
- Simplified Deployments: An intuitive interface simplifies the deployment process.
- Flexible & Compatible: Supports a wide range of languages, frameworks, and databases.
- Automation: Automates deployments from Git providers and handles SSL certificates.
- Scalability: Manages single-server, multi-server, and Docker Swarm deployments.
| Variable | Description | Default |
|---|---|---|
DB_HOST |
Database hostname | postgres |
DB_NAME |
Database name | gsa_db |
DB_USER |
Database user | root |
DB_PASS |
Database password | (see docker-compose.yml) |
API_MAX_RESULTS |
Maximum results per request | 1777 |
CSV_URL |
Source CSV URL | OpenPLZ API URL |
Rate Limiting: Modify nginx/default.conf:
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;PHP Settings: Edit php/custom.ini:
max_execution_time = 300
memory_limit = 512M# Search for streets containing "Haupt"
curl "http://localhost:8080/api/search.php?field=street_name&operator=contains&value=Haupt&limit=10"# Search for streets in Berlin with postal code starting with "10"
curl -G "http://localhost:8080/api/search.php" \
--data-urlencode 'filters=[{"field":"city_name","operator":"equals","value":"Berlin"},{"field":"zip_code","operator":"starts_with","value":"10"}]' \
--data-urlencode 'logic=AND'For complete examples including:
- Programming language integrations (JavaScript, Python, PHP, cURL)
- Advanced filtering and pagination
- Error handling and best practices
- Interactive API testing
Visit the Full API Documentation
This API uses data from the OpenPLZ API project, which provides comprehensive German postal and address data derived from OpenStreetMap.
Data Updates:
- Recommended to setup automatic synchronization twice daily (3:00 AM and 3:00 PM)
- Manual updates available via fetch script
- Change detection ensures only new/modified records are processed
- Complete data integrity checks and logging
Data Coverage:
- All German states and territories
- 500,000+ unique street entries
- Complete postal code coverage
- Administrative boundary information
Q: API returns "Service unavailable" error A: Check if PostgreSQL container is running and healthy:
docker compose ps
docker compose logs postgresQ: No results returned for valid searches A: Verify data has been loaded:
docker exec gsa_php php /var/www/html/fetch_streets.phpQ: Container fails to start A: Check port conflicts and permissions:
sudo netstat -tlnp | grep :8080
ls -la data/postgres/Q: Database connection errors A: Verify database credentials and network:
docker exec -it gsa_db psql -U postgres -d gsa_dbFor high-traffic deployments:
- Increase PHP-FPM worker processes
- Add database indices for frequently searched fields
- Implement caching layer (Redis/Memcached)
- Use connection pooling
- Configure Nginx worker processes
View application logs:
# API request logs
docker compose logs -f nginx
# PHP application logs
docker compose logs -f php-fpm
# Database logs
docker compose logs -f postgresThis project is licensed under the MIT License - see the LICENSE file for details.
- OpenPLZ API for providing comprehensive German address data
- OpenStreetMap contributors for the underlying geographic data
- The PHP, PostgreSQL, Docker and Coolify communities for excellent tools and documentation
- Claude Code for helping me reduce development time massively
Made with ❤️ by Linus Grolmes