diff --git a/src/client/app/common/scripts/note-mixin.ts b/src/client/app/common/scripts/note-mixin.ts
index 4b454f880..e64968007 100644
--- a/src/client/app/common/scripts/note-mixin.ts
+++ b/src/client/app/common/scripts/note-mixin.ts
@@ -83,9 +83,19 @@ export default (opts: Opts = {}) => ({
 			if (this.appearNote.text) {
 				const ast = parse(this.appearNote.text);
 				// TODO: 再帰的にURL要素がないか調べる
-				return unique(ast
+				const urls = unique(ast
 					.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent))
 					.map(t => t.node.props.url));
+
+				// unique without hash
+				// [ http://a/#1, http://a/#2, http://b/#3 ] => [ http://a/#1, http://b/#3 ]
+				const removeHash = x => x.replace(/#[^#]*$/, '');
+
+				return urls.reduce((array, url) => {
+					const removed = removeHash(url);
+					if (!array.map(x => removeHash(x)).includes(removed)) array.push(url);
+					return array;
+				}, []);
 			} else {
 				return null;
 			}
diff --git a/src/client/app/common/views/components/url-preview.vue b/src/client/app/common/views/components/url-preview.vue
index 9c61e4605..20fbcbb04 100644
--- a/src/client/app/common/views/components/url-preview.vue
+++ b/src/client/app/common/views/components/url-preview.vue
@@ -30,7 +30,7 @@
 <script lang="ts">
 import Vue from 'vue';
 import i18n from '../../../i18n';
-import { url as local } from '../../../config';
+import { url as local, lang } from '../../../config';
 
 export default Vue.extend({
 	i18n: i18n('common/views/components/url-preview.vue'),
@@ -89,10 +89,10 @@ export default Vue.extend({
 	},
 
 	created() {
-		const url = new URL(this.url);
+		const requestUrl = new URL(this.url);
 
-		if (this.detail && url.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(url.pathname)) {
-			this.tweetUrl = url;
+		if (this.detail && requestUrl.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(requestUrl.pathname)) {
+			this.tweetUrl = requestUrl;
 			const twttr = (window as any).twttr || {};
 			const loadTweet = () => twttr.widgets.load(this.$refs.tweet);
 
@@ -113,10 +113,15 @@ export default Vue.extend({
 			return;
 		}
 
-		if (url.hostname === 'music.youtube.com')
-			url.hostname = 'youtube.com';
+		if (requestUrl.hostname === 'music.youtube.com') {
+			requestUrl.hostname = 'youtube.com';
+		}
 
-		fetch(`/url?url=${encodeURIComponent(this.url)}`).then(res => {
+		const requestLang = (lang || 'ja-JP').replace('ja-KS', 'ja-JP');
+
+		requestUrl.hash = '';
+
+		fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${requestLang}`).then(res => {
 			res.json().then(info => {
 				if (info.url == null) return;
 				this.title = info.title;
diff --git a/src/server/web/url-preview.ts b/src/server/web/url-preview.ts
index e5b9ff624..310cf88c0 100644
--- a/src/server/web/url-preview.ts
+++ b/src/server/web/url-preview.ts
@@ -12,18 +12,20 @@ module.exports = async (ctx: Koa.BaseContext) => {
 	const meta = await fetchMeta();
 
 	logger.info(meta.summalyProxy
-		? `(Proxy) Getting preview of ${ctx.query.url} ...`
-		: `Getting preview of ${ctx.query.url} ...`);
+		? `(Proxy) Getting preview of ${ctx.query.url}@${ctx.query.lang} ...`
+		: `Getting preview of ${ctx.query.url}@${ctx.query.lang} ...`);
 
 	try {
 		const summary = meta.summalyProxy ? await request.get({
 			url: meta.summalyProxy,
 			qs: {
-				url: ctx.query.url
+				url: ctx.query.url,
+				lang: ctx.query.lang || 'ja-JP'
 			},
 			json: true
 		}) : await summaly(ctx.query.url, {
-			followRedirects: false
+			followRedirects: false,
+			lang: ctx.query.lang || 'ja-JP'
 		});
 
 		logger.succ(`Got preview of ${ctx.query.url}: ${summary.title}`);