diff --git a/locale/translations.go b/locale/translations.go
index 402afe58cf1454fa7b657988ccdd70d07c69945e..298d0e029fb6b16321bbc6e1745b7e0c1ddd3260 100644
--- a/locale/translations.go
+++ b/locale/translations.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.536096032 -0800 PST m=+0.030567687
+// 2017-11-20 17:09:36.257679981 -0800 PST m=+0.024050336
 
 package locale
 
@@ -129,12 +129,13 @@ var Translations = map[string]string{
     "Unable to parse OPML file: %v": "Impossible de lire le fichier OPML : %v",
     "Unable to parse RSS feed: %v": "Impossible de lire ce flux RSS: %v",
     "Unable to parse Atom feed: %v": "Impossible de lire ce flux Atom: %v",
-    "Unable to parse JSON feed: %v": "Impossible de lire ce flux Json: %v"
+    "Unable to parse JSON feed: %v": "Impossible de lire ce flux Json: %v",
+    "Unable to normalize encoding: %v.": "Impossible de normaliser l'encodage : %v."
 }
 `,
 }
 
 var TranslationsChecksums = map[string]string{
 	"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
-	"fr_FR": "e9b3753645cb83a338f48bdc24825e629d568ebd3a65a4be2978ff6b4f3bc380",
+	"fr_FR": "0ff93081d867ab27a190b5cbe6aaed65dbdcd80079ad667b515428a147cb20ee",
 }
diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json
index f7536f680772c86da877952b7132f118f95f2b60..40aa51af4dbf96d3cdb10356512627836163e0a9 100644
--- a/locale/translations/fr_FR.json
+++ b/locale/translations/fr_FR.json
@@ -113,5 +113,6 @@
     "Unable to parse OPML file: %v": "Impossible de lire le fichier OPML : %v",
     "Unable to parse RSS feed: %v": "Impossible de lire ce flux RSS: %v",
     "Unable to parse Atom feed: %v": "Impossible de lire ce flux Atom: %v",
-    "Unable to parse JSON feed: %v": "Impossible de lire ce flux Json: %v"
+    "Unable to parse JSON feed: %v": "Impossible de lire ce flux Json: %v",
+    "Unable to normalize encoding: %v.": "Impossible de normaliser l'encodage : %v."
 }
diff --git a/reader/feed/handler.go b/reader/feed/handler.go
index 27ff126b71e49cde5497185613c770cdd385dab2..c046ad98509d823a2740136b9322303d1cefac46 100644
--- a/reader/feed/handler.go
+++ b/reader/feed/handler.go
@@ -6,14 +6,15 @@ package feed
 
 import (
 	"fmt"
+	"log"
+	"time"
+
 	"github.com/miniflux/miniflux2/errors"
 	"github.com/miniflux/miniflux2/helper"
 	"github.com/miniflux/miniflux2/model"
 	"github.com/miniflux/miniflux2/reader/http"
 	"github.com/miniflux/miniflux2/reader/icon"
 	"github.com/miniflux/miniflux2/storage"
-	"log"
-	"time"
 )
 
 var (
@@ -21,6 +22,7 @@ var (
 	errServerFailure = "Unable to fetch feed (statusCode=%d)."
 	errDuplicate     = "This feed already exists (%s)."
 	errNotFound      = "Feed %d not found"
+	errEncoding      = "Unable to normalize encoding: %v."
 )
 
 // Handler contains all the logic to create and refresh feeds.
@@ -32,7 +34,7 @@ type Handler struct {
 func (h *Handler) CreateFeed(userID, categoryID int64, url string) (*model.Feed, error) {
 	defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:CreateFeed] feedUrl=%s", url))
 
-	client := http.NewHttpClient(url)
+	client := http.NewClient(url)
 	response, err := client.Get()
 	if err != nil {
 		return nil, errors.NewLocalizedError(errRequestFailed, err)
@@ -46,7 +48,12 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string) (*model.Feed,
 		return nil, errors.NewLocalizedError(errDuplicate, response.EffectiveURL)
 	}
 
-	subscription, err := parseFeed(response.Body)
+	body, err := response.NormalizeBodyEncoding()
+	if err != nil {
+		return nil, errors.NewLocalizedError(errEncoding, err)
+	}
+
+	subscription, err := parseFeed(body)
 	if err != nil {
 		return nil, err
 	}
@@ -89,7 +96,7 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
 		return errors.NewLocalizedError(errNotFound, feedID)
 	}
 
-	client := http.NewHttpClientWithCacheHeaders(originalFeed.FeedURL, originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
+	client := http.NewClientWithCacheHeaders(originalFeed.FeedURL, originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
 	response, err := client.Get()
 	if err != nil {
 		customErr := errors.NewLocalizedError(errRequestFailed, err)
@@ -111,8 +118,12 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
 
 	if response.IsModified(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) {
 		log.Printf("[Handler:RefreshFeed] Feed #%d has been modified\n", feedID)
+		body, err := response.NormalizeBodyEncoding()
+		if err != nil {
+			return errors.NewLocalizedError(errEncoding, err)
+		}
 
-		subscription, err := parseFeed(response.Body)
+		subscription, err := parseFeed(body)
 		if err != nil {
 			originalFeed.ParsingErrorCount++
 			originalFeed.ParsingErrorMsg = err.Error()
diff --git a/reader/http/client.go b/reader/http/client.go
index 745ff0db17c4ef24f1dbad594b1a0d419f8fc926..edb3c86b3e7e8088c9a7b1dc959a0410c2217754 100644
--- a/reader/http/client.go
+++ b/reader/http/client.go
@@ -7,23 +7,26 @@ package http
 import (
 	"crypto/tls"
 	"fmt"
-	"github.com/miniflux/miniflux2/helper"
 	"log"
 	"net/http"
 	"net/url"
 	"time"
+
+	"github.com/miniflux/miniflux2/helper"
 )
 
-const HTTP_USER_AGENT = "Miniflux <https://miniflux.net/>"
+const userAgent = "Miniflux <https://miniflux.net/>"
 
-type HttpClient struct {
+// Client is a HTTP Client :)
+type Client struct {
 	url                string
 	etagHeader         string
 	lastModifiedHeader string
 	Insecure           bool
 }
 
-func (h *HttpClient) Get() (*ServerResponse, error) {
+// Get execute a GET HTTP request.
+func (h *Client) Get() (*Response, error) {
 	defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[HttpClient:Get] url=%s", h.url))
 	u, _ := url.Parse(h.url)
 
@@ -39,7 +42,7 @@ func (h *HttpClient) Get() (*ServerResponse, error) {
 		return nil, err
 	}
 
-	response := &ServerResponse{
+	response := &Response{
 		Body:         resp.Body,
 		StatusCode:   resp.StatusCode,
 		EffectiveURL: resp.Request.URL.String(),
@@ -59,7 +62,7 @@ func (h *HttpClient) Get() (*ServerResponse, error) {
 	return response, err
 }
 
-func (h *HttpClient) buildClient() http.Client {
+func (h *Client) buildClient() http.Client {
 	if h.Insecure {
 		transport := &http.Transport{
 			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
@@ -71,9 +74,9 @@ func (h *HttpClient) buildClient() http.Client {
 	return http.Client{}
 }
 
-func (h *HttpClient) buildHeaders() http.Header {
+func (h *Client) buildHeaders() http.Header {
 	headers := make(http.Header)
-	headers.Add("User-Agent", HTTP_USER_AGENT)
+	headers.Add("User-Agent", userAgent)
 
 	if h.etagHeader != "" {
 		headers.Add("If-None-Match", h.etagHeader)
@@ -86,10 +89,12 @@ func (h *HttpClient) buildHeaders() http.Header {
 	return headers
 }
 
-func NewHttpClient(url string) *HttpClient {
-	return &HttpClient{url: url, Insecure: false}
+// NewClient returns a new HTTP client.
+func NewClient(url string) *Client {
+	return &Client{url: url, Insecure: false}
 }
 
-func NewHttpClientWithCacheHeaders(url, etagHeader, lastModifiedHeader string) *HttpClient {
-	return &HttpClient{url: url, etagHeader: etagHeader, lastModifiedHeader: lastModifiedHeader, Insecure: false}
+// NewClientWithCacheHeaders returns a new HTTP client that send cache headers.
+func NewClientWithCacheHeaders(url, etagHeader, lastModifiedHeader string) *Client {
+	return &Client{url: url, etagHeader: etagHeader, lastModifiedHeader: lastModifiedHeader, Insecure: false}
 }
diff --git a/reader/http/response.go b/reader/http/response.go
index 49e9f19681f8b8f9faaee44945b15f99dcef9188..b2dfb54798273349f1f233861be1aa19d16b75fe 100644
--- a/reader/http/response.go
+++ b/reader/http/response.go
@@ -5,8 +5,10 @@
 package http
 
 import "io"
+import "golang.org/x/net/html/charset"
 
-type ServerResponse struct {
+// Response wraps a server response.
+type Response struct {
 	Body         io.Reader
 	StatusCode   int
 	EffectiveURL string
@@ -15,18 +17,25 @@ type ServerResponse struct {
 	ContentType  string
 }
 
-func (s *ServerResponse) HasServerFailure() bool {
-	return s.StatusCode >= 400
+// HasServerFailure returns true if the status code represents a failure.
+func (r *Response) HasServerFailure() bool {
+	return r.StatusCode >= 400
 }
 
-func (s *ServerResponse) IsModified(etag, lastModified string) bool {
-	if s.StatusCode == 304 {
+// IsModified returns true if the resource has been modified.
+func (r *Response) IsModified(etag, lastModified string) bool {
+	if r.StatusCode == 304 {
 		return false
 	}
 
-	if s.ETag != "" && s.LastModified != "" && (s.ETag == etag || s.LastModified == lastModified) {
+	if r.ETag != "" && r.LastModified != "" && (r.ETag == etag || r.LastModified == lastModified) {
 		return false
 	}
 
 	return true
 }
+
+// NormalizeBodyEncoding make sure the body is encoded in UTF-8.
+func (r *Response) NormalizeBodyEncoding() (io.Reader, error) {
+	return charset.NewReader(r.Body, r.ContentType)
+}
diff --git a/reader/icon/finder.go b/reader/icon/finder.go
index 54d509f5bafbd75749a6b0771e927e6bd27fc7e8..fe6e86dfbf580ff650ce5a0c5875760bb8088890 100644
--- a/reader/icon/finder.go
+++ b/reader/icon/finder.go
@@ -6,13 +6,14 @@ package icon
 
 import (
 	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+
 	"github.com/miniflux/miniflux2/helper"
 	"github.com/miniflux/miniflux2/model"
 	"github.com/miniflux/miniflux2/reader/http"
 	"github.com/miniflux/miniflux2/reader/url"
-	"io"
-	"io/ioutil"
-	"log"
 
 	"github.com/PuerkitoBio/goquery"
 )
@@ -20,7 +21,7 @@ import (
 // FindIcon try to find the website's icon.
 func FindIcon(websiteURL string) (*model.Icon, error) {
 	rootURL := url.GetRootURL(websiteURL)
-	client := http.NewHttpClient(rootURL)
+	client := http.NewClient(rootURL)
 	response, err := client.Get()
 	if err != nil {
 		return nil, fmt.Errorf("unable to download website index page: %v", err)
@@ -80,7 +81,7 @@ func parseDocument(websiteURL string, data io.Reader) (string, error) {
 }
 
 func downloadIcon(iconURL string) (*model.Icon, error) {
-	client := http.NewHttpClient(iconURL)
+	client := http.NewClient(iconURL)
 	response, err := client.Get()
 	if err != nil {
 		return nil, fmt.Errorf("unable to download iconURL: %v", err)
diff --git a/reader/subscription/finder.go b/reader/subscription/finder.go
index 7314644d6d58c3695985a6a3bb63a1035645c911..cb6fbf20a7a7b4cab8ddd055c1c827c9db39a617 100644
--- a/reader/subscription/finder.go
+++ b/reader/subscription/finder.go
@@ -7,14 +7,15 @@ package subscription
 import (
 	"bytes"
 	"fmt"
+	"io"
+	"log"
+	"time"
+
 	"github.com/miniflux/miniflux2/errors"
 	"github.com/miniflux/miniflux2/helper"
 	"github.com/miniflux/miniflux2/reader/feed"
 	"github.com/miniflux/miniflux2/reader/http"
 	"github.com/miniflux/miniflux2/reader/url"
-	"io"
-	"log"
-	"time"
 
 	"github.com/PuerkitoBio/goquery"
 )
@@ -28,7 +29,7 @@ var (
 func FindSubscriptions(websiteURL string) (Subscriptions, error) {
 	defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[FindSubscriptions] url=%s", websiteURL))
 
-	client := http.NewHttpClient(websiteURL)
+	client := http.NewClient(websiteURL)
 	response, err := client.Get()
 	if err != nil {
 		return nil, errors.NewLocalizedError(errConnectionFailure, err)
diff --git a/server/static/bin.go b/server/static/bin.go
index 0a7f6798f03c45c9fa814506473676fbb0d577f3..b95023b7a387dc04aa14cffc9d9d4a05269ec057 100644
--- a/server/static/bin.go
+++ b/server/static/bin.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.511191455 -0800 PST m=+0.005663110
+// 2017-11-20 17:09:36.239163817 -0800 PST m=+0.005534172
 
 package static
 
diff --git a/server/static/css.go b/server/static/css.go
index 50c0ccab34137b1a9354b86267368216ebd68c80..bfe6b6a6a994b9bf1419142bc72d0fab36f2b641 100644
--- a/server/static/css.go
+++ b/server/static/css.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.51268594 -0800 PST m=+0.007157595
+// 2017-11-20 17:09:36.24112331 -0800 PST m=+0.007493665
 
 package static
 
diff --git a/server/static/js.go b/server/static/js.go
index f8524454882a5a8c2c5685f6763e1f82620e30f2..816728e9fc62301327b1467b0018423794fa8f1c 100644
--- a/server/static/js.go
+++ b/server/static/js.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.51596478 -0800 PST m=+0.010436435
+// 2017-11-20 17:09:36.242888415 -0800 PST m=+0.009258770
 
 package static
 
diff --git a/server/template/common.go b/server/template/common.go
index acb1db9494d06b332cb50e19a489b048c4a93345..16db6eaec3ed9f891b09eba8914a7708786b0e82 100644
--- a/server/template/common.go
+++ b/server/template/common.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.53440477 -0800 PST m=+0.028876425
+// 2017-11-20 17:09:36.256513528 -0800 PST m=+0.022883883
 
 package template
 
diff --git a/server/template/views.go b/server/template/views.go
index 856927f6518b0963830df6b8da9986d33f5a9e94..8b224b61893470184ee776d232c2fea4841458cf 100644
--- a/server/template/views.go
+++ b/server/template/views.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.517489275 -0800 PST m=+0.011960930
+// 2017-11-20 17:09:36.24386504 -0800 PST m=+0.010235395
 
 package template
 
diff --git a/sql/sql.go b/sql/sql.go
index 1200ea420c2d16e7033e7b52f6e80468380dff79..5f327c87ad13b4c174b9c7973b5cca9b9531e12f 100644
--- a/sql/sql.go
+++ b/sql/sql.go
@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
-// 2017-11-20 16:03:46.509724835 -0800 PST m=+0.004196490
+// 2017-11-20 17:09:36.23789781 -0800 PST m=+0.004268165
 
 package sql