contactlookup
Self hosted contacts API for searching through a VCF file for contact records
Installation
Using pip:
pip install contactlookup
Using poetry:
poetry add contactlookup
Using pipenv:
pipenv install contactlookup
Quick Start
Running as a Docker container
Serve the contacts in the accompanying sample contacts.vcf file:
docker build -t contactlookup .
docker run -p 127.0.0.1:8000:8000 contactlookup
# Daemonize the container
docker run -d -p 127.0.0.1:8000:8000 contactlookup
To serve your own VCF file, mount it at /app/contacts.vcf. Mounting it
read-only is a good idea:
docker run -d -p 127.0.0.1:8000:8000 \
-v /path/to/contacts.vcf:/app/contacts.vcf:ro \
contactlookup
To make it reachable from other machines, publish the port on all interfaces and require an API key:
docker run -d -p 8000:8000 \
-e CONTACTLOOKUP_API_KEY="$(openssl rand -hex 32)" \
-v /path/to/contacts.vcf:/app/contacts.vcf:ro \
contactlookup
The image runs as a non-root user and has a health check on /health.
To stop the container:
docker ps # Get the container ID
docker stop <container_id>
Running as a CLI application
As a script:
contactlookup --help
contactlookup # Start the API server, and serve the contacts in the accompanying contacts.vcf file
contactlookup -f /path/to/contacts.vcf # Start the API server, and serve the contacts in the VCF file
contactlookup -f /path/to/contacts.vcf --host 0.0.0.0 --port 9000 # listen on all interfaces, port 9000
The CLI listens on 127.0.0.1:8000 by default.
Configuration
| Setting | CLI flag | Environment variable | Default |
|---|---|---|---|
| Address to listen on | --host |
CONTACTLOOKUP_HOST |
127.0.0.1 (0.0.0.0 in Docker) |
| Port | --port |
CONTACTLOOKUP_PORT |
8000 |
| API key | CONTACTLOOKUP_API_KEY |
none (API is open) |
When CONTACTLOOKUP_API_KEY is set, every /contacts request needs an
X-API-Key header:
curl -H "X-API-Key: $CONTACTLOOKUP_API_KEY" http://localhost:8000/contacts/fname/jeff
/, /health and /docs stay open. The key is left out of the CLI flags on
purpose, so it doesn't show up in your shell history or ps. If you listen on
anything other than localhost without a key, the app prints a warning at
startup.
Responses
200with{"contacts": [...]}for searches, which is an empty list when nothing matches404for/contacts/{id}when there's no contact with that id401when an API key is configured and the header is missing or wrong503while the contacts aren't loaded yet
As a module:
python -m contactlookup --help
Using the API
You can search for contacts by
- first name,
- phone number, or
- email address.
The search is case-insensitive. Partial matches are not yet supported.
Search using web browser
Open your web browser and navigate to http://localhost:8000/docs to see the
API documentation. Depending on your setup, you may need to replace localhost.
Search using curl
Search by email
curl -X 'GET' \
'http://localhost:8000/contacts/email/jeffnewman@example.net' \
-H 'accept: application/json'
Search by phone number
curl -X 'GET' \
'http://localhost:8000/contacts/phone/+993-547-8840782' \
-H 'accept: application/json'
The use of +, -, ., and () in the phone number is optional.
Response:
{
"contacts": [
{
"id": 1,
"first_name": "KRISTEN",
"last_name": "PEREZ",
"other_names": null,
"company": "Crescendo Associates",
"title": null,
"nickname": "NICKNAME",
"birthday": "1966-08-19",
"phone_numbers": [
{
"id": null,
"number": "7194259182505",
"contact_id": 1,
"type": null
},
{
"id": null,
"number": "9935478840782",
"contact_id": 1,
"type": null
}
],
"addresses": [
{
"id": null,
"street": "36346 Hall Stream",
"city": "CHRISTOPHERSTAD",
"state": "CA",
"postal_code": "73297",
"contact_id": 1,
"type": null,
"country": "USA"
},
{
"id": null,
"street": "196 Purple Sage Cres",
"city": "WINNIPEG",
"state": "MB",
"postal_code": "R3X 1V7",
"contact_id": 1,
"type": null,
"country": "CA"
}
],
"emails": [
{
"id": null,
"email": "jacksonkimberly@example.net",
"type": null,
"contact_id": 1
}
]
}
]
}
Search by first name
curl -X 'GET' \
'http://localhost:8000/contacts/fname/jeff' \
-H 'accept: application/json'
Results are returned in JSON format:
{
"contacts": [
{
"id": 3,
"first_name": "JEFF",
"last_name": "",
"other_names": null,
"company": "Viagenie",
"title": null,
"nickname": null,
"birthday": "1949-01-29",
"phone_numbers": [
{
"id": null,
"number": "3632144414254",
"contact_id": 3,
"type": null
}
],
"addresses": [
{
"id": null,
"street": "2360 Bean Tunnel",
"city": "SOUTH JAMES",
"state": "DC",
"postal_code": "96916",
"contact_id": 3,
"type": null,
"country": "MONTSERRAT"
},
{
"id": null,
"street": "26767 Khan Dam",
"city": "EAST MARISAMOUTH",
"state": "MA",
"postal_code": "26701",
"contact_id": 3,
"type": null,
"country": "BRAZIL"
},
{
"id": null,
"street": "63932 Natasha Fords",
"city": "DEBRAVIEW",
"state": "VT",
"postal_code": "22957",
"contact_id": 3,
"type": null,
"country": "NAMIBIA"
}
],
"emails": [
{
"id": null,
"email": "allentaylor@example.net",
"type": null,
"contact_id": 3
},
{
"id": null,
"email": "daniel03@example.net",
"type": null,
"contact_id": 3
},
{
"id": null,
"email": "martinezveronica@example.net",
"type": null,
"contact_id": 3
}
]
},
{
"id": 4,
"first_name": "JEFF",
"last_name": "NEWMAN",
"other_names": null,
"company": "Hollywood",
"title": null,
"nickname": null,
"birthday": "1955-03-29",
"phone_numbers": [
{
"id": null,
"number": "161555531122",
"contact_id": 4,
"type": null
}
],
"addresses": [
{
"id": null,
"street": "123 Hollywood St",
"city": "BEVERLEY-HILLS",
"state": "CA",
"postal_code": "22957",
"contact_id": 4,
"type": null,
"country": "USA"
}
],
"emails": [
{
"id": null,
"email": "jeffnewman@example.net",
"type": null,
"contact_id": 4
}
]
}
]
}
Metadata
Release files for contactlookup 3.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| contactlookup-3.0.0.tar.gz | 31.1 kB | With provenance | Details for contactlookup-3.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| contactlookup-3.0.0-py3-none-any.whl | Python 3 | none | any | Details for contactlookup-3.0.0-py3-none-any.whl |
Total release size: 60.8 kB
Release files / contactlookup-3.0.0.tar.gz
| Download URL | contactlookup-3.0.0.tar.gz |
|---|---|
| Size | 31.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ee8a277440ecf3881890952c18d24ad7ca2a62a09d3426c3c1be1844b8fc3cf
|
|
BLAKE2b-256 checksum How to use checksums |
644e0af749de70aee269af4156c644ce10ef25b6f9926801f47dbe058e2ee608
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logRelease files / contactlookup-3.0.0-py3-none-any.whl
| Download URL | contactlookup-3.0.0-py3-none-any.whl |
|---|---|
| Size | 29.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6834e12ea64cab13cae746ddf460b9998a3acc775c3b4d24625bcb6e302a6ea7
|
|
BLAKE2b-256 checksum How to use checksums |
c31c3d478a348ad356f02beff6ac34791aa4b601e712bc187ef65c7c78ee691b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logSecurity for contactlookup 3.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for contactlookup-3.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.