json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) は、JSON として読もうとした文字列が、先頭(0文字目)から JSON ではなかったときのエラーです。 多くの場合、JSON の書き方の間違いではなく、そもそも JSON が来ていません。

char 0 のときに、実際に来ていたもの(確認環境):

来ていたもの 例 よくある場面
空の文字列 '' API が 204(No Content)を返した、ファイルが空
HTML <!DOCTYPE html>... 404・500 のエラーページ、ログイン画面へのリダイレクト
BOM 付きのファイル {...} Windows のメモ帳・Excel で保存した JSON(メッセージは Unexpected UTF-8 BOM)

まず、読もうとした中身を表示します。

print(repr(text[:200]))          # 文字列なら
print(r.status_code, r.headers.get('Content-Type'), repr(r.text[:200]))   # requests なら

確認環境:Python 3.10・3.12・3.13・3.14、requests 2.34(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JSONDecodeError: Expecting valueの直し方」

エラー位置の読み方

JSONDecodeError: Expecting value: line 1 column 7 (char 6)
                 ~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~
                 何が期待されたか  どこで止まったか(行・列・先頭からの文字数)
部分 意味
line 1 column 7 1行目の7文字目(1から数える)
(char 6) 先頭から数えて6文字目(0から数える)
char 0 先頭の1文字目から JSON ではない
except json.JSONDecodeError as e:
    print(e.msg, e.lineno, e.colno)
    print(repr(e.doc[max(0, e.pos - 20): e.pos + 20]))    # 止まった位置の前後

e.doc に読もうとした文字列、e.pos に止まった位置が入っています(Python 公式ドキュメント)。前後を表示すると、どこが間違っているかがすぐ分かります。

メッセージ別の原因(確認環境)

読んだ文字列 メッセージ
''(空) Expecting value: line 1 column 1 (char 0)
' '(空白だけ) Expecting value: line 1 column 4 (char 3)
'<!DOCTYPE html>...' Expecting value: line 1 column 1 (char 0)
"{'a': 1}"(シングルクォート) Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
'{"a": None}'・'{"a": True}'(Python の書き方) Expecting value: line 1 column 7 (char 6)
'{"a": 1,}'(最後にカンマ) 3.13 以降:Illegal trailing comma before end of object/3.12 以前:Expecting property name ...
'{"a":1}\n{"a":2}'(1行1つの JSON) Extra data: line 2 column 1 (char 8)
'{"a": 1 "b": 2}'(カンマ抜け) Expecting ',' delimiter
'{"a": "x'(閉じていない) Unterminated string starting at
BOM 付きのファイルを encoding='utf-8' で読む Unexpected UTF-8 BOM (decode using utf-8-sig)

Python 3.13 からは、最後のカンマに Illegal trailing comma という分かりやすいメッセージが出ました。 '{"a": NaN}' は、エラーにならずに nan として読まれました(Python の json モジュールは、既定で NaN を受け付けます)。

requests の r.json() で出るとき

ローカルのサーバーで、いろいろな応答を返して r.json() を呼びました。

応答 status_code Content-Type 結果
正常な JSON 200 application/json {'a': 1}
404 の HTML 404 text/html Expecting value: line 1 column 1 (char 0)
204(中身なし) 204 なし Expecting value: line 1 column 1 (char 0)
ログイン画面へリダイレクト 200(r.history に 302) text/html Expecting value: line 1 column 1 (char 0)

リダイレクトの例では、status_code が 200 なのに HTML が返っていました。 認証の期限切れで、ログイン画面に飛ばされた形です。r.history に 302 が残っていることで気づけます。

r = requests.get(url, timeout=10)
r.raise_for_status()                                  # 4xx・5xx なら HTTPError
if 'application/json' not in r.headers.get('Content-Type', ''):
    raise ValueError(f'JSON ではない応答: {r.status_code} {r.text[:200]!r}')
data = r.json()

requests の公式ドキュメントでも、r.json() が成功しても通信の成功とは限らないので、raise_for_status() か status_code で確かめるよう書かれています。

落とし穴:except json.JSONDecodeError で捕まらない

>>> isinstance(e, json.JSONDecodeError)       # r.json() で出た例外
False

確認環境(simplejson が入っている環境)では、r.json() の例外は、標準の json.JSONDecodeError の仲間ではなく、except json.JSONDecodeError: では捕まりませんでした。 requests の例外は、入っている JSON のライブラリによって元のクラスが変わります。

書き方 捕まるか
except json.JSONDecodeError: 環境によって捕まらない
except requests.exceptions.JSONDecodeError: 捕まる(requests の公式ドキュメントの書き方)
except ValueError: 捕まる

ファイルを読むとき

with open('data.json', encoding='utf-8-sig') as f:   # BOM があってもなくても読める
    data = json.load(f)

utf-8-sig は、BOM があれば取り除き、無ければそのまま読みました。 Windows で作られた JSON を読む可能性があるなら、utf-8-sig にしておくと安全です。

ファイルの中身 直し方
空 読む前に os.path.getsize() で確かめる
1行1つの JSON(JSON Lines) for line in f: json.loads(line)
Python の dict を str() したもの(シングルクォート・None) 出力する側で json.dumps を使う。受け取ったものは ast.literal_eval で読める

"{'a': 1, 'b': None}" のような、Python の dict を文字列にしたものは JSON ではありません。 確認環境では ast.literal_eval で読めましたが、本来は出力する側を json.dumps に直します。

確認の手順(チェックリスト)

順番 確認すること 方法
1 何が来ていたか repr(text[:200])
2 char 0 か 先頭から JSON でない:空・HTML・BOM
3 API なら status_code・Content-Type・r.history
4 char 0 以外 e.doc[e.pos-20:e.pos+20] で前後を見る
5 例外の捕まえ方 requests.exceptions.JSONDecodeError
6 ファイル encoding='utf-8-sig'、JSON Lines は1行ずつ

よくある質問

Q. JavaScript でも同じエラーが出ます。 A. JavaScript の JSON.parse では Unexpected token '<' などのメッセージになります。関連記事の「Unexpected token '<' in JSONの原因と直し方|fetch」で扱っています。

まとめ

  • char 0 は、先頭から JSON ではない。多くは 空・HTML・BOM
  • まず repr(text[:200]) で中身を見る
  • API は status_code・Content-Type・r.history。200 でもログイン画面のことがある
  • except json.JSONDecodeError では、requests の例外を捕まえられない環境がある
  • シングルクォートは Expecting property name enclosed in double quotes、最後のカンマは 3.13 から Illegal trailing comma
  • ファイルは utf-8-sig で読む

参考・出典

確認日はいずれも 2026年10月11日です。

  • Python ドキュメント「json — JSON encoder and decoder」:https://docs.python.org/3/library/json.html
  • Requests「Quickstart」(JSON Response Content):https://requests.readthedocs.io/en/latest/user/quickstart/

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JSONDecodeError: Expecting valueの直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?