{"id":37645476,"url":"https://github.com/kanedata/find-that-postcode","last_synced_at":"2026-01-16T11:25:47.106Z","repository":{"id":49448306,"uuid":"88757615","full_name":"kanedata/find-that-postcode","owner":"kanedata","description":"A server for getting information about postcodes, with an elasticsearch back end","archived":false,"fork":false,"pushed_at":"2025-11-22T09:33:30.000Z","size":4995,"stargazers_count":16,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-22T11:25:20.230Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kanedata.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["kanedata"]}},"created_at":"2017-04-19T14:56:47.000Z","updated_at":"2025-11-17T14:19:31.000Z","dependencies_parsed_at":"2024-06-05T11:00:29.998Z","dependency_job_id":"49eb4bf8-e87b-465d-ba44-7ac357d0a20f","html_url":"https://github.com/kanedata/find-that-postcode","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kanedata/find-that-postcode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanedata%2Ffind-that-postcode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanedata%2Ffind-that-postcode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanedata%2Ffind-that-postcode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanedata%2Ffind-that-postcode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kanedata","download_url":"https://codeload.github.com/kanedata/find-that-postcode/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanedata%2Ffind-that-postcode/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T06:30:42.265Z","status":"ssl_error","status_checked_at":"2026-01-16T06:30:16.248Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-16T11:25:47.045Z","updated_at":"2026-01-16T11:25:47.101Z","avatar_url":"https://github.com/kanedata.png","language":"JavaScript","funding_links":["https://github.com/sponsors/kanedata"],"categories":[],"sub_categories":[],"readme":"# Find that Postcode\n\nThis project creates an elasticsearch index based on the UK postcode file, and\nruns a webserver on top of it for making queries. It's like a more lightweight\nand less sophisticated version of [MapIt](https://mapit.mysociety.org.uk/).\n\n## Setup\n\n### 1. Setup elasticsearch\n\n[Follow the instructions](https://www.elastic.co/downloads/elasticsearch) to\ndownload and install elasticsearch.\n\nRun the server. At the moment the scripts only work on a default server of\n`localhost:9200` but a future version will have configurable host and port.\n\n### 2. Install python dependencies\n\nYou'll need to install the python `elasticsearch` and `flask` libraries, either\ndirectly through `pip` or by running a virtual environment and running:\n\n```bash\npip install -r requirements.txt\n```\n\nThe code is written in python 3 and hasn't been tested in python 2.\n\n### 3. Point flask to the app\n\nFlask needs to know which app it's running. The easiest way to do this is to create\na file called `.env` in the project directory, and add the following contents:\n\n```bash\nFLASK_APP=findthatpostcode\nFLASK_ENV=development\n\n# S3 credentials for boundaries\nS3_REGION=XXXXXXXX\nS3_ENDPOINT=XXXXXXXX\nS3_ACCESS_ID=XXXXXXXX\nS3_SECRET_KEY=XXXXXXXX\nS3_BUCKET=XXXXXXXX\n```\n\n### 4. Create elasticsearch indexes\n\nRun `flask init-db` to create the needed index and mappings\nbefore data import.\n\n### 5. Import postcodes\n\nRun the following to import the data and save postcodes to the\nelasticsearch index:\n\n```bash\nflask import nspl\n```\n\nThis will then run the import process, fetching the latest version of the\nright file. It takes a while to run as there are over\n2.5 million postcodes. The data will be around 1.3 GB in size on the disk.\n\n### 6. Import area codes\n\nRun the following to import the code history database and register of geographic codes.\n\n```bash\nflask import rgc\nflask import chd\nflask import msoanames # imports the names for MSOAs from House of Commons Library\n```\n\nThe URL of the files used can be customised with the `--url` parameter. Unfortunately the\nONS geoportal doesn't provide a persistent URL to the latest data.\n\n### 6. Import boundaries (optional)\n\nBoundaries are uploaded as individual area files to S3 storage.\n\nBoundary files can be found on the [ONS Geoportal](http://geoportal.statistics.gov.uk/datasets?q=Latest_Boundaries\u0026sort_by=name\u0026sort_order=asc).\nGenerally the \"Generalised Clipped\" versions should be used to minimise the file\nsize. Open each boundary file link and find the \"API\" link on the right hand\nside, and copy the `GeoJSON` link, or download the file.\n\nThese files are the latest available at April 2017:\n\n- Countries: \u003chttps://opendata.arcgis.com/datasets/b789ba2f70fe45eb92402cee87092730_0.geojson\u003e\n- Westminster Parliamentary Constituencies: \u003chttps://opendata.arcgis.com/datasets/094f326b0b1247e3bcf1eb7236c24679_0.geojson\u003e\n- Counties and unitary authorities: \u003chttps://opendata.arcgis.com/datasets/0de4288db3774cb78e45b8b74e9eab31_0.geojson\u003e\n- Local Authority Districts: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Local_Authority_Districts_May_2022_UK_BGC_V3/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n- Regions: \u003chttps://opendata.arcgis.com/datasets/284d82f437554938b0d0fbb3c6522007_0.geojson\u003e\n- CCGs: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Clinical_Commissioning_Groups_April_2021_EN_BGC/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n- European electoral regions: \u003chttps://opendata.arcgis.com/datasets/20595dbf22534e20944c9cee42c665b3_0.geojson\u003e\n- Local Enterprise Partnerships: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/LEP_MAY_2021_EN_BGC_V2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n- NHS Commissioning Regions: \u003chttps://opendata.arcgis.com/datasets/edcbf58c70004d0f8d44501d07c38fe9_0.geojson\u003e\n- National Parks: \u003chttps://opendata.arcgis.com/datasets/f41bd8ff39ce4a2393c2f454006ea60a_0.geojson\u003e\n- Police Force areas: \u003chttps://opendata.arcgis.com/datasets/282af275c1a24c2ea64ff9e05bdd7d7d_0.geojson\u003e\n- Travel to Work Areas: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Travel_to_Work_Areas_December_2011_UK_BGC_v2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n- Major Towns and Cities: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/TCITY_2015_EW_BGG_V2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n- Combined Authorities: \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Combined_Authorities_December_2021_EN_BGC/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e\n\nThese files are large:\n\n- Parishes (11,000): \u003chttps://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Parishes_May_2022_EW_BGC/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\u003e --code-field=par22cd\n- Wards (8,900): \u003chttps://opendata.arcgis.com/datasets/d2dce556b4604be49382d363a7cade72_0.geojson\u003e - Didn't work\n- LSOAs (35,000): \u003chttps://opendata.arcgis.com/datasets/e993add3f1944437bc91ec7c76100c63_0.geojson\u003e - Didn't work\n- MSOAs (7,200): \u003chttps://opendata.arcgis.com/datasets/29fdaa2efced40378ce8173b411aeb0e_2.geojson\u003e - Didn't work\n- Built-up Areas (5,800): \u003chttps://opendata.arcgis.com/datasets/f6684981be23404e83321077306fa837_0.geojson\u003e\n- Built-up Area Sub-divisions (1,800): \u003chttps://opendata.arcgis.com/datasets/1f021bb824ee4820b353b4b58fab6df5_0.geojson\u003e\n\nImport the boundary files by running:\n\n```bash\nflask import boundaries \"https://opendata.arcgis.com/datasets/094f326b0b1247e3bcf1eb7236c24679_0.geojson\"\n```\n\nYou can add more than one URL to each import script.\n\n### 7. Import placenames (optional)\n\nA further related dataset is placenames. The [ONS has a list of these](http://geoportal.statistics.gov.uk/datasets/a6c138d17ac54532b0ca8ee693922f10_0)\nwhich can be imported using the `import placenames` command. An entry for each\nplacename is added to the `geo_placenames` elasticsearch index.\n\n```bash\nflask import placenames\n```\n\nThe `--url` parameter can be used to customise the URL used.\n\n### 7. Import statistics (optional)\n\nStatistics can be added to areas, using ONS data. The available statistics are\nadded to LSOAs, but could also be added to other areas.\n\n```bash\nflask import imd2025\nflask import imd2019\nflask import imd2015\n```\n\nThe `--url` parameter can be used to customise the URL used to get the data.\n\n### Run tests\n\n```bash\npython -m pytest tests\n```\n\n## Using the data\n\n### Run the server\n\nThe project comes with a simple server (using the [flask](https://flask.palletsprojects.com/) framework) allowing\nyou to look at postcodes. The server returns either html pages (using `.html`)\nor json data by default.\n\nRun the server by:\n\n```bash\nflask run\n```\n\nBy default the server is available at \u003chttp://localhost:5000/\u003e.\n\n#### Server endpoints\n\nThe server has a number of possible uses:\n\n- `/postcodes/SW1A+1AA.html` gives information about a particular postcode.\n- `/areas/E09000033.html` gives information about an area, including example postcodes.\n- `/areas/search.html?q=Winchester` finds any areas containing a search query.\n- `/areatypes/laua.html` gives information about a type of area, including lists of\n  example codes.\n- `/areatypes.html` lists all the possible area types.\n- `/points/53.490911,-2.095804.html` gives details of the postcode closest to the\n  latitude, longitude point. If it's more than 10km from the nearest postcode it's\n  assumed to be outside the UK.\n\n### Elasticsearch REST api\n\nThe data is also now available in an elasticsearch index to be used in other local\napplications using the elasticsearch REST api.\n\n#### Find details on a postcode\n\n```bash\ncurl \"http://localhost:9200/geo_postcode/_doc/SW1A+1AA?pretty\"\n```\n\n```json\n{\n  \"_index\": \"postcode\",\n  \"_type\": \"postcode\",\n  \"_id\": \"SW1A 1AA\",\n  \"_version\": 1,\n  \"found\": true,\n  \"_source\": {\n    \"bua11\": \"E34004707\",\n    \"oac11\": \"2C3\",\n    \"park\": \"E99999999\",\n    \"osnrth1m\": 179645,\n    \"buasd11\": \"E35000546\",\n    \"lsoa11\": \"E01004736\",\n    \"lsoa21\": \"E01004736\",\n    \"pcon\": \"E14000639\",\n    \"pct\": \"E16000057\",\n    \"nuts\": \"E05000644\",\n    \"pcds\": \"SW1A 1AA\",\n    \"ccg\": \"E38000031\",\n    \"osgrdind\": 1,\n    \"eer\": \"E15000007\",\n    \"hlthau\": \"E18000007\",\n    \"imd\": 16419,\n    \"ward\": \"E05000644\",\n    \"wz11\": \"E33031119\",\n    \"ctry\": \"E92000001\",\n    \"oseast1m\": 529090,\n    \"pcd2\": \"SW1A 1AA\",\n    \"laua\": \"E09000033\",\n    \"rgn\": \"E12000007\",\n    \"location\": {\n      \"lon\": -0.141588,\n      \"lat\": 51.501009\n    },\n    \"lat\": 51.501009,\n    \"usertype\": 1,\n    \"cty\": \"E99999999\",\n    \"ttwa\": \"E30000234\",\n    \"lep1\": \"E37000023\",\n    \"pcd\": \"SW1A1AA\",\n    \"teclec\": \"E24000014\",\n    \"dointr\": \"1980-01-01T00:00:00\",\n    \"oa11\": \"E00023938\",\n    \"oa21\": \"E00023938\",\n    \"long\": -0.141588,\n    \"pfa\": \"E23000001\",\n    \"ru11ind\": \"A1\",\n    \"ruc21\": \"UN1\",\n    \"hro\": \"E19000003\",\n    \"msoa11\": \"E02000977\",\n    \"msoa21\": \"E02000977\",\n    \"lep2\": null,\n    \"doterm\": null\n  }\n}\n```\n\n#### Find details on an area\n\n```bash\ncurl \"http://localhost:9200/geo_area/_doc/E00046056?pretty\"\n```\n\n```json\n{\n  \"_index\": \"postcode\",\n  \"_type\": \"code\",\n  \"_id\": \"E00046056\",\n  \"_version\": 2,\n  \"found\": true,\n  \"_source\": {\n    \"code\": \"E00046056\",\n    \"name\": \"\",\n    \"name_welsh\": null,\n    \"statutory_instrument_id\": \"1111/1001\",\n    \"statutory_instrument_title\": \"GSS re-coding strategy\",\n    \"date_start\": \"2009-01-01T00:00:00\",\n    \"date_end\": null,\n    \"parent\": \"E01009081\",\n    \"entity\": \"E00\",\n    \"owner\": \"ONS\",\n    \"active\": true,\n    \"areaehect\": 3.75,\n    \"areachect\": 3.75,\n    \"areaihect\": 0,\n    \"arealhect\": 3.75,\n    \"sort_order\": \"E00046056\",\n    \"predecessor\": [\"00CNFN0006\"],\n    \"successor\": [],\n    \"equivalents\": {\n      \"ons\": \"00CNFN0006\"\n    }\n  }\n}\n```\n\n## Todo / future features\n\n- Find areas containing a point\n\n## Dokku setup\n\n```bash\n# create app\ndokku apps:create find-that-postcode\n\n# add permanent data storage\ndokku storage:mount find-that-postcode /var/lib/dokku/data/storage/find-that-postcode:/data\n\n# enable domain\ndokku domains:enable find-that-postcode\ndokku domains:add find-that-postcode findthatpostcode.uk\n\n# elasticsearch\nsudo dokku plugin:install https://github.com/dokku/dokku-elasticsearch.git elasticsearch\ndokku elasticsearch:create find-that-postcode-es\ndokku elasticsearch:link find-that-postcode-es find-that-postcode\n\n# SSL\nsudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git\ndokku config:set --no-restart find-that-postcode DOKKU_LETSENCRYPT_EMAIL=your@email.tld\ndokku letsencrypt find-that-postcode\ndokku letsencrypt:cron-job --add\n```\n\n### 2. Add as a git remote and push\n\nOn local machine:\n\n```bash\ngit remote add dokku dokku@SERVER_HOST:find-that-postcode\ngit push dokku main\n```\n\n### 3. Setup and run import\n\nOn Dokku server run:\n\n```bash\n# setup and run import\ndokku config:set find-that-postcode FLASK_APP=findthatpostcode\ndokku config:set find-that-postcode S3_REGION=XXXXXXXX\ndokku config:set find-that-postcode S3_ENDPOINT=XXXXXXXX\ndokku config:set find-that-postcode S3_ACCESS_ID=XXXXXXXX\ndokku config:set find-that-postcode S3_SECRET_KEY=XXXXXXXX\ndokku config:set find-that-postcode S3_BUCKET=XXXXXXXX\ndokku run find-that-postcode flask init-db\ndokku run find-that-postcode flask import nspl --year=2011\ndokku run find-that-postcode flask import nspl --year=2021\ndokku run find-that-postcode flask import rgc\ndokku run find-that-postcode flask import chd\ndokku run find-that-postcode flask import msoanames\ndokku run find-that-postcode flask import imd2025\ndokku run find-that-postcode flask import imd2019\ndokku run find-that-postcode flask import imd2015\ndokku run find-that-postcode flask import placenames\n\n# import boundaries\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/7be6a3c1be3b4385951224d2f522470a_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/094f326b0b1247e3bcf1eb7236c24679_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/0de4288db3774cb78e45b8b74e9eab31_0.geojson\ndokku run find-that-postcode flask import boundaries https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Local_Authority_Districts_May_2022_UK_BGC_V3/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/284d82f437554938b0d0fbb3c6522007_0.geojson\ndokku run find-that-postcode flask import boundaries https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Clinical_Commissioning_Groups_April_2021_EN_BGC/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/20595dbf22534e20944c9cee42c665b3_0.geojson\ndokku run find-that-postcode flask import boundaries https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/LEP_MAY_2021_EN_BGC_V2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/edcbf58c70004d0f8d44501d07c38fe9_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/f41bd8ff39ce4a2393c2f454006ea60a_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/282af275c1a24c2ea64ff9e05bdd7d7d_0.geojson\ndokku run find-that-postcode flask import boundaries https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Travel_to_Work_Areas_December_2011_UK_BGC_v2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/TCITY_2015_EW_BGG_V2/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/c6bd4568af5947519cf266b80a94de2e_0.geojson\n\n# large boundary files\ndokku run find-that-postcode flask import boundaries --code-field=par18cd https://services1.arcgis.com/ESMARspQHYMw9BZ9/arcgis/rest/services/Parishes_May_2022_EW_BGC/FeatureServer/0/query?outFields=*\u0026where=1%3D1\u0026f=geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/d2dce556b4604be49382d363a7cade72_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/e993add3f1944437bc91ec7c76100c63_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/29fdaa2efced40378ce8173b411aeb0e_2.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/f6684981be23404e83321077306fa837_0.geojson\ndokku run find-that-postcode flask import boundaries https://opendata.arcgis.com/datasets/1f021bb824ee4820b353b4b58fab6df5_0.geojson\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanedata%2Ffind-that-postcode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkanedata%2Ffind-that-postcode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanedata%2Ffind-that-postcode/lists"}