out of curiosity I worked out the encoding, at least partly. It takes the last 4 bits of the first byte and the last 6 bits of the remaining two from each triplet, so we can directly decode like this: cdecode[s_String] := FromCharacterCode@FromDigits[ Join @@ MapThread[IntegerDigits[FromDigits[#1, 16], 2][[#2 ;;]] &, {StringTake[#,Array[{3 # - 1, 3 #} &, 3]], {-4, -6, -6}}], 2] & /@ StringTake[s,Array[{9 # - 8, 9 #} &, Floor[StringLength@s/9] ]]//StringJoin cdecode["=E6=B5=8B=E8=AF=95=E4=B8=80=E4=B8=8B"] > same string No doubt `URLDecode` is the more robust way to go. Note there are 8 bits that have been ignored here. Presumably the 'E' signifies the start of a 3-byte code - that's ignored here an should be checked.