Question: I want to add flag images such as below to my bar chart:  I have tried AnnotationBbox but that shows with a square outline. Can anyone tell how to achieve this exactly as above image? Edit: Below is my code ax.barh(y = y, width = values, color = r, height = 0.8) height = 0.8 for i, (value, url) in enumerate(zip(values, image_urls)): response = requests.get(url) img = Image.open(BytesIO(response.content)) width, height = img.size left = 10 top = 10 right = width-10 bottom = height-10 im1 = img.crop((left, top, right, bottom)) print(im1.size) im1 ax.imshow(im1, extent = [value - 6, value, i - height / 2, i + height / 2], aspect = 'auto', zorder = 2)  Edit 2: height = 0.8 for j, (value, url) in enumerate(zip(ww, image_urls)): response = requests.get(url) img = Image.open(BytesIO(response.content)) ax.imshow(img, extent = [value - 6, value - 2, j - height / 2, j + height / 2], aspect = 'auto', zorder = 2) ax.set_xlim(0, max(ww)*1.05) ax.set_ylim(-0.5, len(yy) - 0.5) plt.tight_layout()  

Answer: You need the images in a .png format with a transparent background. (Software such as Gimp or ImageMagick could help in case the images don't already have the desired background.) With such an image, plt.imshow() can place it in the plot. The location is given via extent=[x0, x1, y0, y1]. To prevent imshow to force an equal aspect ratio, add aspect='auto'. zorder=2 helps to get the image on top of the bars. Afterwards, the plt.xlim and plt.ylim need to be set explicitly (also because imshow messes with them.) The example code below used 'ada.png' as that comes standard with matplotlib, so the code can be tested standalone. Now it is loading flags from countryflags.io, following this post. Note that the image gets placed into a box in data coordinates (6 wide and 0.9 high in this case). This box will get stretched, for example when the plot gets resized. You might want to change the 6 to another value, depending on the x-scale and on the figure size. import numpy as np import matplotlib.pyplot as plt # import matplotlib.cbook as cbook import requests from io import BytesIO labels = ['CW', 'CV', 'GW', 'SX', 'DO'] colors = ['crimson', 'dodgerblue', 'teal', 'limegreen', 'gold'] values = 30 + np.random.randint(5, 20, len(labels)).cumsum() height = 0.9 plt.barh(y=labels, width=values, height=height, color=colors, align='center') for i, (label, value) in enumerate(zip(labels, values)): # load the image corresponding to label into img # with cbook.get_sample_data('ada.png') as image_file: # img = plt.imread(image_file) response = requests.get(f'https://www.countryflags.io/{label}/flat/64.png') img = plt.imread(BytesIO(response.content)) plt.imshow(img, extent=[value - 8, value - 2, i - height / 2, i + height / 2], aspect='auto', zorder=2) plt.xlim(0, max(values) * 1.05) plt.ylim(-0.5, len(labels) - 0.5) plt.tight_layout() plt.show()   PS: As explained by Ernest in the comments and in this post, using OffsetImage the aspect ratio of the image stays intact. (Also, the xlim and ylim stay intact.) The image will not shrink when there are more bars, so you might need to experiment with the factor in OffsetImage(img, zoom=0.65) and the x-offset in AnnotationBbox(..., xybox=(-25, 0)). An extra option could place the flags outside the bar for bars that are too short. Or at the left of the y-axis. The code adapted for horizontal bars could look like: import numpy as np import requests from io import BytesIO import matplotlib.pyplot as plt from matplotlib.offsetbox import OffsetImage, AnnotationBbox def offset_image(x, y, label, bar_is_too_short, ax): response = requests.get(f'https://www.countryflags.io/{label}/flat/64.png') img = plt.imread(BytesIO(response.content)) im = OffsetImage(img, zoom=0.65) im.image.axes = ax x_offset = -25 if bar_is_too_short: x = 0 ab = AnnotationBbox(im, (x, y), xybox=(x_offset, 0), frameon=False, xycoords='data', boxcoords="offset points", pad=0) ax.add_artist(ab) labels = ['CW', 'CV', 'GW', 'SX', 'DO'] colors = ['crimson', 'dodgerblue', 'teal', 'limegreen', 'gold'] values = 2 ** np.random.randint(2, 10, len(labels)) height = 0.9 plt.barh(y=labels, width=values, height=height, color=colors, align='center', alpha=0.8) max_value = values.max() for i, (label, value) in enumerate(zip(labels, values)): offset_image(value, i, label, bar_is_too_short=value < max_value / 10, ax=plt.gca()) plt.subplots_adjust(left=0.15) plt.show()