It seems that custom markers only work with URLs and not local image files.
This works:
icon = folium.features.CustomIcon('http://www.pngall.com/wp-content/uploads/2016/05/Iron-Man.png', icon_size=(50,50))
folium.Marker([43, -79],
popup='Iron Man',
icon=icon
).add_to(geo_map)
This does not work:
icon = folium.features.CustomIcon('Iron-Man.png', icon_size=(50,50))
folium.Marker([43, -79],
popup='Iron Man',
icon=icon
).add_to(geo_map)
If the Iron-Man.png served along side the map? If not It won't work. If true and it does not work we have a bug.
I can confirm everything works as expected, closing this.

Maybe we could add a self-contained version that would encode the image in the HTML. I do have a goal to do that for everything in folium in a consistent way, but it will take a while.
If you want to send a PR to solve that for icons take a look at the ImageOverlay plugin and try to implement something along those lines.
@nanodan this code will work with local image file.
import base64
encoded = base64.b64encode(open('Iron-Man.png', 'rb').read())
decoded = base64.b64decode(encoded)
icon_url = BytesIO(decoded)
icon = folium.features.CustomIcon(icon_url, icon_size=(50,50))
folium.Marker([43, -79],
popup='Iron Man',
icon=icon
).add_to(geo_map)
but for list of markers, the code only shows the first icon. :(
@dvu4 Thank you for sharing! That worked for me
@ocefpaf could you please explain how you serve local files to folium?
@nanodan I have solved this problem by using @dvu4 answer and then doing deep copies of the objects (so it isn't needed to parse each element each time):
import copy
m = folium.Map()
icon = BytesIO(base64.b64decode(base64.b64encode(open(os.path.join(os.getcwd(),"icons","Weather_Icons_05_hail-512.png"), 'rb').read())))
for iteration in range(10):
marker_icon = copy.copy(icon)
folium.Marker(location=[temp_coord[iteration][0], temp_coord[iteration][1],icon=marker_icon ).add_to(m)
but for list of markers, the code only shows the first icon. :(
This has come up in #744 as well. Though it is expected behavior at the moment that an icon has to be created for each marker, PR's to improve on this are welcome.
I tried @dvu4 suggestion but it results in a TypeError: Object of type 'BytesIO' is not JSON serializable
Is there a better method for achieving this, or are custom icons still not supported?
@nathan3leaf please paste the full traceback. I think I faced that error too. Let's see if I can help you
Traceback (most recent call last):
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\threading.py", line 916, in _bootstrap_inner
self.run()
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/natha/Dropbox/PYTHON_PROJECTS/analysisSuite.py", line 13453, in runAnalysis
self.createInteractiveMap(centerName=sites.text(), coords=[lat, lon])
File "C:/Users/natha/Dropbox/PYTHON_PROJECTS/analysisSuite.py", line 12556, in createInteractiveMap
MAPPING().getInteractiveMap(centerName=centerName, coords=[lat, lon], layers=layers, output=False)
File "C:/Users/natha/Dropbox/PYTHON_PROJECTS/analysisSuite.py", line 10994, in getInteractiveMap
clientIcon = folium.features.CustomIcon(icon_url, icon_size=(50, 50))
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\features.py", line 1146, in __init__
self.icon_url = image_to_url(icon_image)
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\utilities.py", line 102, in image_to_url
url = json.loads(json.dumps(image))
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\json\__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Users\natha\AppData\Local\Programs\Python\Python36-32\lib\json\encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'BytesIO' is not JSON serializable
Thank you @davidolmo your help is very much appreciated.
Ok I see. It seems like the utility function that parses images for CustomIcon (image_to_url) no longer supports BytesIO format in the current version. However, it supports the path! (so it will transform the file automatically to Bytes for you). What I did is directly pass the path of the image:
icon_path = r"C:\some_path\icon.png"
icon = folium.features.CustomIcon(icon_image=icon_path ,icon_size=icons_size)
marker=folium.Marker([row["coord"].y,row["coord"].x],popup=popup,icon=icon).add_to(feature_groups[alert_icon_name])
@davidolmo well, you are correct. I was able to make some modifications using the method you posted and it's working perfectly. Thanks for the helpful info!
thank you @davidolmo this really helped me.....
Most helpful comment
Ok I see. It seems like the utility function that parses images for CustomIcon (image_to_url) no longer supports BytesIO format in the current version. However, it supports the path! (so it will transform the file automatically to Bytes for you). What I did is directly pass the path of the image:
icon_path = r"C:\some_path\icon.png"icon = folium.features.CustomIcon(icon_image=icon_path ,icon_size=icons_size)marker=folium.Marker([row["coord"].y,row["coord"].x],popup=popup,icon=icon).add_to(feature_groups[alert_icon_name])