I provided some relevant info on encoding/decoding text in this response: https://stackoverflow.com/a/34662963/2957811
To add to that here, it's important to think of text in one of two possible states: 'encoded' and 'decoded'
'decoded' means it is in an internal representation by your interpreter/libraries that can be used for character manipulation (e.g. searches, case conversion, substring slicing, character counts, ...) or display (looking up a code point in a font and drawing the glyph), but cannot be passed in or out of the running process.
'encoded' means it is a byte stream that can be passed around as can any other data, but is not useful for manipulation or display.
If you've worked with serialized objects before, consider 'decoded' to be the useful object in memory and 'encoded' to be the serialized version.
'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'
is your encoded (or serialized) version, presumably encoded with cp1251. This encoding needs to be right because that's the 'language' used to serialize the characters and is needed to recreate the characters in memory.
You need to decode this from it's current encoding (cp1251) into python unicode characters, then re-encode it as a utf8 byte stream. The answerer that suggested d.decode('cp1251').encode('utf8')
had this right, I am just hoping to help explain why that should work.