 <ol> <li><p>The variables <code>jpg_data</code> and <code>png_data</code> are lists containing captured URLs. Your loops iterate over each URL, placing the URL string in the variable <code>image</code>. Then, in both loops, you write the URL string to the file, not the actual image. It actually looks like the commented out <code>urllib</code> lines would do the trick, instead of what you're currently doing now.</p></li> <li><p>The <code>.write()</code> function expects you to give it an object that matches the mode of the file. When you call <code>open(..., 'wb')</code>, you're saying to open the file in <code>write</code> and <code>binary</code> mode, which means that you need to give it <code>bytes</code> instead of <code>str</code>.</p></li> </ol> <p>Bytes are the fundamental way everything is stored in a computer. Everything is a series of bytes -- the data on your hard drive, and the data you send and receive on the Internet. Bytes don't really have meaning on their own -- each one is just 8 bits strung together. The meaning depends on how you <em>interpret</em> the bytes. For instance, you could interpret a single byte as representing a number from 0 to 255. Or, you could interpret it as a number from -128 to 127 (both of these are common). You could also assign these "numbers" to characters, and interpret a sequence of bytes as text. However, this only allows you to represent 256 characters, and there are many more than that in the world's various languages. So, there are multiple ways of representing text as sequences of bytes. These are called "character encodings". The most popular modern one is "UTF-8".</p> <p>In Python, a <code>bytes</code> object is just a series of bytes. It has no special meaning -- nobody has said what it represents yet. If you want to use that as text, you need to decode it, using one of the character encodings. Once you do that (<code>.decode('UTF-8')</code>), you have a <code>str</code> object. In order to write it to disk (or the network), your <code>str</code> will have to eventually be <em>encoded</em> back into bytes. When you open a file in text mode, Python chooses your computer's default encoding, and it will decode everything you read using that, and encode everything you write with it. However, when you open a file in <code>b</code> mode, Python expects that you will give it <code>bytes</code>, and so it throws an error when you give it a <code>str</code> instead. Since you know the HTML file you downloaded and put in <code>data</code> is text, it would have been best for you to save it to a file in text mode. However, encoding it as <code>UTF-8</code> and writing it to a binary file works too, as long as your system's default encoding is <code>UTF-8</code>. In general, when you have a <code>str</code> and you want to write it to a file, open the file in text mode (just don't pass <code>b</code> in the mode parameter) and let Python pick the encoding, since it knows better than you do!</p> <p>For more info on the character sets and encoding stuff (which I only glossed over), you really should read <a href="http://www.joelonsoftware.com/articles/Unicode.html" rel="nofollow">this</a> article.</p>