diff --git a/.gitignore b/.gitignore
index e53ff510047602c1f1616ceec5d2fc1397c8c77d..9ec5d1ae7e4ad9ec18a90c297bfc48aa4d7369a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,4 +145,4 @@ dmypy.json
 cython_debug/
 weights/yolov3-veges_best.weights
 weights/yolov3-vattenhallen_best.weights
-src/creds.py
+creds.py
diff --git a/img/WIN_20211103_21_16_18_Pro.jpg b/img/WIN_20211103_21_16_18_Pro.jpg
deleted file mode 100644
index 27b585013a55f2853a29424ccfeb124cc719edb1..0000000000000000000000000000000000000000
Binary files a/img/WIN_20211103_21_16_18_Pro.jpg and /dev/null differ
diff --git a/img/annotations/WIN_20211103_21_16_18_Pro.txt b/img/annotations/WIN_20211103_21_16_18_Pro.txt
deleted file mode 100644
index 7fd6b5a6fdeeb230cbf138bde46f802ea1928095..0000000000000000000000000000000000000000
--- a/img/annotations/WIN_20211103_21_16_18_Pro.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-3 1055.2865 148.5889 443.2753 73.4710 99.5100
-1 188.5453 22.3466 85.2053 49.0357 99.9200
-3 1048.2261 134.2752 271.3041 76.3464 99.9600
diff --git a/img/locations/WIN_20211101_17_19_37_Pro.txt b/img/locations/WIN_20211101_17_19_37_Pro.txt
deleted file mode 100644
index fdd0b107edc822f4b6d0a84b83d0b5d910757b21..0000000000000000000000000000000000000000
--- a/img/locations/WIN_20211101_17_19_37_Pro.txt
+++ /dev/null
@@ -1 +0,0 @@
-350 700 -100
\ No newline at end of file
diff --git a/img/readme.md b/img/readme.md
deleted file mode 100644
index d6af6012b91c95a8c1a29b38ffad1f453ca7a0e9..0000000000000000000000000000000000000000
--- a/img/readme.md
+++ /dev/null
@@ -1,2 +0,0 @@
-This folder is to store all the photos of the planting bed, 
-and is supposed to be cleaned each time after detection.
\ No newline at end of file
diff --git a/src/utils/download.py b/src/utils/download.py
new file mode 100644
index 0000000000000000000000000000000000000000..67caace59ae348c9a5181e23e9d0faebee39516b
--- /dev/null
+++ b/src/utils/download.py
@@ -0,0 +1,102 @@
+"""Download images from Farmbot instance."""
+import argparse
+import os
+from pathlib import Path
+from typing import List
+
+import requests
+
+import utils.creds as creds
+
+
+# note: download only returns 100 at a time!
+# note: we are currently ignoreing placeholders
+
+DEBUG_SKIP_DELETE_FILES = True
+
+IMG_FILE_SUFFIX = ".jpg"
+
+REQUEST_HEADERS = {
+    "Authorization": "Bearer " + creds.token,
+    "content-type": "application/json",
+}
+
+
+def download_images(directory: os.PathLike, delete_after=False) -> List[str]:
+    """Download all images on server, optionally deleting after download.
+
+    Parameters
+    ----------
+    directory
+        directory to store images in
+
+    Raises
+    ------
+    RuntimeError
+        If the server gives a bad response (not 200).
+
+    Returns
+    -------
+    list of str
+        List of filepaths with downloaded images
+    """
+    response = requests.get("https://my.farmbot.io/api/images", headers=REQUEST_HEADERS)
+    json_response = response.json()
+
+    if response.status_code != 200:
+        raise RuntimeError(f"Got status code {response.status_code}.")
+
+    print(json_response)
+    print(f"Got a response containing {len(json_response)}")
+
+    if len(json_response) < 1:
+        return []
+
+    img_paths = []
+
+    for img_dict in json_response:
+        if "placehold.it" in img_dict["attachment_url"]:
+            print("IGNORE! placeholder", img_dict["id"])
+            continue
+
+        server_path: str = img_dict["meta"]["name"]
+
+        if not server_path.startswith("/tmp/images"):
+            print("meta name does not start with /tmp/images")
+            continue
+
+        filename = Path(server_path).stem + IMG_FILE_SUFFIX
+        filepath = Path(directory) / filename
+
+        print(">", filepath)
+
+        # download image from google storage and save locally
+        if filepath.exists():
+            print("File exists, skipping")
+            continue
+
+        img_req = requests.get(img_dict["attachment_url"], allow_redirects=True)
+
+        with filepath.open(mode="wb") as fp:
+            fp.write(img_req.content)
+
+        img_paths.append(filepath)
+
+        # post delete from cloud storage
+        if delete_after:
+            requests.delete(
+                f"https://my.farmbot.io/api/images/{img_dict['id']}",
+                headers=REQUEST_HEADERS,
+            )
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description="Farmbot YOLO image downloader")
+    parser.add_argument(
+        "download_dir", type=Path, help="Directory to download images too."
+    )
+    parser.add_argument("-d", "--delete", action="store_true")
+
+    args = parser.parse_args()
+
+    download_images(args.download_dir, delete_after=args.delete)